LA 3026 && POJ 1961 Period (利用kmp中的next数组找最小的循环节 )

来源:互联网 发布:戏曲下载软件 编辑:程序博客网 时间:2024/05/21 11:36
周期( Period, SEERC 2004, LA3026
给定一个长度为n的字符串S, 求它每个前缀的最短循环节。 换句话
说, 对于每个i2≤i≤n) , 求一个最大的整数K1( 如果K存在) , 使得
S的前i个字符组成的前缀是某个字符串重复K次得到。 输出所有存在Ki
和对应的K
比如对于字符串aabaabaabaab, 只有当i26912K存在, 且
分别为2234
【 输入格式】
输入包含多组数据。 每组数据第一行为正整数n2≤n≤106) , 第二行
为一个字符串S。 输入结束标志为n0
【 输出格式】
对于每组数据, 按照从小到大的顺序输出每个i和对应的K, 一对整
数占一行。
【 分析】

如图3-22所示, 根据后缀函数的定义, 错位部分长度为if[i]


3-22
如果这i个字符组成一个周期串, 那么错位部分恰好是一个循环
节, 因此if[i]k*i( 注意k1, 因此if[i]不能等于i, 即必须有f[i]
0) 。 不难证明反过来也成立。 

3-22
如果这i个字符组成一个周期串, 那么错位部分恰好是一个循环
节, 因此if[i]k*i( 注意k1, 因此if[i]不能等于i, 即必须有f[i]
0) 。 不难证明反过来也成立。 。 代码如下。


//题目中的关键信息一定要找到 //利用kmp中的next数组找最小的循环节 #include<cstdio>#include<iostream>#include<cstring>using namespace std;const int mn=1000010;int Next[mn],n;char s[mn];void getNext(){int i=0,j=-1;Next[0]=-1;while(i<n){if(j==-1||s[i]==s[j]) Next[++i]=++j;else j=Next[j];}}int main(){int T=1;while(~scanf("%d",&n)&&n){scanf("%s",s);getNext();printf("Test case #%d\n",T++);for(int i=2;i<=n;i++)if(Next[i]>0&&i%(i-Next[i])==0) printf("%d %d\n",i,i/(i-Next[i]));puts("");}return 0;}


阅读全文
1 0
原创粉丝点击