HDU 3374 KMP 最大表示法 最小表示法
来源:互联网 发布:淘宝小铺名称能改吗 编辑:程序博客网 时间:2024/05/20 04:13
String Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1586 Accepted Submission(s): 703
String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
abcderaaaaaaababab
1 1 6 11 6 1 61 3 2 3
对于一个字符串S,求S的循环的同构字符串S’中字典序最小的一个。
由于语言能力有限,还是用实际例子来解释比较容易:
设S=bcad,且S’是S的循环同构的串。S’可以是bcad或者cadb,adbc,dbca。而且最小表示的S’是adbc。
对于字符串循环同构的最小表示法,其问题实质是求S串的一个位置,从这个位置开始循环输出S,得到的S’字典序最小。
一种朴素的方法是设计i,j两个指针。其中i指向最小表示的位置,j作为比较指针。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j] 设指针k,分别从i和j位置向下比较,直到S[i] != S[j]
如果S[i+k] > S[j+k] i=j,j=i+1
否则j++
返回i
起初,我想在j指针后移的过程中加入一个优化。就是j每次不是加1,而是移动到l位置。其中,l>j且S[l]<=S[j]。但是,即使加入这一优化,在遇到bbb…bbbbbba这样的字符串时复杂度将退化到O(n^2)。
注意到,朴素算法的缺陷在于斜体的情况下i指针的移动太少了。针对这一问题改进就得到了最小表示法的算法。最小表示法的算法思路是维护两个指针i,j。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j] 设指针k,分别从i和j位置向下比较,直到S[i] != S[j]
如果S[i+k] > S[j+k] i=i+k
否则j++
返回i和j的小者
注意到上面两个算法唯一的区别是粗体的一行。这一行就把复杂度降到O(n)了。
//以上为抄袭。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int next[1000010];
void getnext(char p[])
{
int j=-1,i=0,len=strlen(p);
next[0]=-1;
while(i<len)
{
if(j==-1||p[i]==p[j])
{
i++;j++;next[i]=j;
}
else j=next[j];
}
}
int Min(char p[])
{
int j=0,k=1,l=0,i,len=strlen(p);
while(k<len&&j<len&&l<len)
{
i=p[(j+l)%len]-p[(k+l)%len];
if(i==0) l++;
else
{
if(i>0) j=j+l+1;
if(i<0) k=k+l+1;
if(j==k) k++; //当JK移动到同一个位置时 避免比较两个相同的起点的字符串
l=0;
}
}
return min(j,k);
}
int Max(char p[])
{
int j=0,k=1,l=0,i,len=strlen(p);
while(j<len&&k<len&&l<len)
{
i=p[(j+l)%len]-p[(k+l)%len];
if(i==0) l++;
else
{
if(i<0) j=j+l+1;
if(i>0) k=k+l+1;
if(k==j) k++; //当JK移动到同一个位置时 避免比较两个相同的起点的字符串
l=0;
}
}
return min(j,k);
}
int main()
{
char ch[1000010];
while(~scanf("%s",ch))
{
getnext(ch);
int len=strlen(ch);
int j=len-next[len];
if(len%j==0)
len/=j;
else len=1;
printf("%d %d %d %d\n",Min(ch)+1,len,Max(ch)+1,len);
}
}
- HDU 3374 KMP 最大表示法 最小表示法
- HDU 3374 String Problem(最小最大表示法+KMP)
- HDU 3374 String Problem KMP-最小最大表示法
- HDU 3374String Problem(最大最小表示法+KMP)
- hdu 3374 String Problem(字符串最小最大表示法+kmp)
- hdu 3374 String Problem (kmp+最大最小表示法)
- HDU 3374 String Problem (KMP+最大最小表示法)
- HDU 3374 String Problem(最大最小表示法+kmp)
- hdu 3374 String Problem(KMP+最大最小表示法)
- HDU 3374 KMP-最小最大表示法的原理详解
- hdu 3374 最小表示法加 KMP
- HDU(3374) (KMP + 最小表示法)
- HDU 3374 (KMP 最小表示法)
- HDU 5442 Favorite Donut 最大最小表示法+KMP
- hdu5442 最小最大表示法+kmp
- hdu3374String Problem kmp+最大最小表示法
- HDU 3374 String Problem(KMP求周期+求串最大最小表示法)
- HDU 3374 String Problem (KMP+最小最大表示法)【模板】
- hdoj.2077 汉诺塔IV 20140808
- 表达式求值
- spring 官方下载地址(Spring Framework 3.2.x&Spring Framework 4.0.x)
- HDU 1166 敌兵布阵 (我的树状数组加线段树点修改模板)
- 函数名与函数指针
- HDU 3374 KMP 最大表示法 最小表示法
- ibatis 学习
- >>> FilterDispatcher <<< is deprecated! Please use the new filters!
- 你的收派件范围被固定了吗
- SpringMVC2.5.X支持JSON
- 最短路径
- makefile 中 $@ $^ %< 使用
- Android开源项目第二篇——工具库篇
- 校验是否含有中文字符