本文主要是介绍poj 1961 Period (KMP 最短循环节),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1、http://poj.org/problem?id=1961
2、题目大意:
给定一个长度为n的字符串s,求它的每个前缀的最短循环节。换句话说,对于每个i(2<=i<=n),求一个最大的整数K>1(如果K存在),使得S的前i个字符组成的前缀是某个字符串重复K次得到的。输出所有存在K的i和对应的K。
比如对于字符串aabaabaabaab, 只有当i=2,6,9,12时K存在,且分别为2,2,3,4
题目的样例解释
给一个长度是n的字符串s,假如我们可以找到一个字符串A,可以使得A循环K次后得到一个字符串B,而B正好是s的前缀,输出B的长度,输出K
例如aaa这个样例,A=a,那么A循环K=2的时候得到的B就是aa,输出2,2
A=a,那么A循环K=3的时候得到的B就是aaa,输出3,3
aabaabaabaab这个有12个字母的样例
当A=a的时候,A循环K=2次得到B=aa,输出2,2
当A=aab的时候,A循环K=2次得到B=aabaab,输出6,2
当A=aab的时候,A循环K=3次得到B=aabaabaab,输出9,3
当A=aab的时候,A循环K=4次得到B=aabaabaabaab,输出12,4
3、只用KMP模板中的求模式值的函数
个数为i/(i-f[i])
4、题目:
Description
Input
number zero on it.
Output
Sample Input
3 aaa 12 aabaabaabaab 0
Sample Output
Test case #1 2 2 3 3Test case #2 2 2 6 2 9 3 12 4
#include<stdio.h>
#include<string.h>
#define N 1000005
char str[N];
int f[N];
void getFail(char *p, int *f)
{int m=strlen(p);f[0]=f[1]=0;for(int i=1; i<m; ++i){int j=f[i];while(j && p[i]!=p[j])j=f[j];f[i+1] = p[i]==p[j]?1+j:0;}
}
int main()
{int n,cas=0;while(scanf("%d",&n)){if(n==0)break;cas++;printf("Test case #%d\n",cas);getchar();memset(str,0,sizeof(str));for(int i=0; i<n; i++)scanf("%c",&str[i]);getFail(str,f);for(int i=2; i<=n; i++){if(f[i]>0&&i%(i-f[i])==0)printf("%d %d\n",i,i/(i-f[i]));}printf("\n");}return 0;
}
这篇关于poj 1961 Period (KMP 最短循环节)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!