KMP算法及应用
KMP算法用来解决一系列字符串单模式匹配问题,其以难理解,难记忆著称。其next数组的构造就如同AC自动机中的fail指针,就是如果匹配失败,字符串应从哪里开始继续匹配。这里的next数组表示:next[i]=前i个字符的公共最长前后缀长度。觉得对于KMP算法,这篇写的不错——http://www.cnblogs.com/c-cloud/p/3224788.html。
现在来讲一下应用。
给定两个字符串a和b,我们可以定义一些操作:a*b为将字符串a和字符串b连接起来,比如a= "aoe",b= "jkw",那么a*b= "aoejkw"。进一步,我们可以有指数操作,a^0= "", a^1=a, a^2=a*a, a^n=a*(a^(n-1))=a*a*…*a (n个a)
现在给你一个字符串,你可以将它看成是a^n的形式,比如字符串"abababab",可以认为是"abab"^2, 也可以是"abababab"^1,还可以是"ab"^4。
现在问题是,给定的字符串,我们想让它变成a^n中的n达到最大,那么这个n最大是多少?例如:"abababab"最大的n是4。
输入
第一行,一个整数m,表示有m个字符串。
接下来m行每行输入一个只含小写字母的字符串。
输出
输出m行,对于每行输出相应字符串的最大n。
样例输入
3 abcde aaaaaa abababab
样例输出
1 6 4
提示
这道题一看觉得不是特别会,暴力算法老王的bloghttp://www.cnblogs.com/TUncleWangT/p/7162665.html讲了,正解就是运用了KMP算法里的next数组。我们令原字符串长度为S,重复字符串长度为T,则S=K*T,由定义可知next[S]=(K-1)*T;所以S-next[S]=T,判断一下整除就好了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; char str[1000005]; int next[1000005]; void make_next() { int len=strlen(str),q,k; next[0]=0; for(q=1,k=0;q<len;q++) { while(k>0&&str[q]!=str[k]) { k=next[k-1]; } if(str[k]==str[q]) k++; next[q]=k; } } void Debug() { int len=strlen(str); for(int i=0;i<len;i++) cout<<next[i]<<' '; } void work() { int tmp=strlen(str)-next[strlen(str)-1]; if(strlen(str)%tmp==0) cout<<(strlen(str)/tmp)<<endl;else cout<<1<<endl; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%s",str); make_next(); work(); } }