题目:https://www.acwing.com/problem/content/143/
一个字符串的前缀是从第一个字符开始的连续若干个字符,例如”abaab”共有5个前缀,分别是a, ab, aba, abaa, abaab。
我们希望知道一个N位字符串S的前缀是否具有循环节。
换言之,对于每一个从头开始的长度为 i (i>1)的前缀,是否由重复出现的子串A组成,即 AAA…A (A重复出现K次,K>1)。
如果存在,请找出最短的循环节对应的K值(也就是这个前缀串的所有可能重复节中,最大的K值)。
输入格式
输入包括多组测试数据,每组测试数据包括两行。
第一行输入字符串S的长度N。
第二行输入字符串S。
输入数据以只包括一个0的行作为结尾。
输出格式
对于每组测试数据,第一行输出 “Test case #” 和测试数据的编号。
接下来的每一行,输出具有循环节的前缀的长度i和其对应K,中间用一个空格隔开。
前缀长度需要升序排列。
在每组测试数据的最后输出一个空行。
数据范围
2≤N≤10000002≤N≤1000000
输入样例:
3
aaa
4
abcd
12
aabaabaabaab
0
输出样例:
Test case #1
2 2
3 3
Test case #2
Test case #3
2 2
6 2
9 3
12 4
题意:
没啥好的,简单的next数组求循环节长度,很水。向我最开始学kmp的时候用的是 len-next[len],以为只有总长度才能用这个公式。
根据题意从1到n遍历next数组, i-next[i]求的是当前状态的循环节长度,当i%(i-next[i])==0的时候说明这一段完全由该循环节组成,个数是 i/(i-next[i])。
代码:
1 #include <map> 2 #include <stack> 3 #include <queue> 4 #include <cmath> 5 #include <string> 6 #include <limits> 7 #include <cstdio> 8 #include <vector> 9 #include <cstdlib> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #define Scc(c) scanf("%c",&c) 14 #define Scs(s) scanf("%s",s) 15 #define Sci(x) scanf("%d",&x) 16 #define Sci2(x, y) scanf("%d%d",&x,&y) 17 #define Sci3(x, y, z) scanf("%d%d%d",&x,&y,&z) 18 #define Scl(x) scanf("%I64d",&x) 19 #define Scl2(x, y) scanf("%I64d%I64d",&x,&y) 20 #define Scl3(x, y, z) scanf("%I64d%I64d%I64d",&x,&y,&z) 21 #define Pri(x) printf("%d\n",x) 22 #define Prl(x) printf("%I64d\n",x) 23 #define Prc(c) printf("%c\n",c) 24 #define Prs(s) printf("%s\n",s) 25 #define For(i,x,y) for(int i=x;i<y;i++) 26 #define For_(i,x,y) for(int i=x;i<=y;i++) 27 #define FFor(i,x,y) for(int i=x;i>y;i--) 28 #define FFor_(i,x,y) for(int i=x;i>=y;i--) 29 #define Mem(f, x) memset(f,x,sizeof(f)) 30 #define LL long long 31 #define ULL unsigned long long 32 #define MAXSIZE 1000010 33 #define INF 0x3f3f3f3f 34 35 #include <bits/stdc++.h> 36 const int mod=1e9+7; 37 const double PI = acos(-1.0); 38 39 //using namespace std; 40 char s[MAXSIZE]; 41 int next[MAXSIZE]; 42 int n; 43 void getnext() 44 { 45 int i=0,j=-1; 46 next[0]=-1; 47 while(i<n) 48 { 49 if(j!=-1&&s[i]!=s[j]) 50 j=next[j]; 51 else 52 { 53 i++; 54 j++; 55 next[i]=j; 56 } 57 } 58 } 59 int main() 60 { 61 int k=1; 62 while(scanf("%d",&n)&&n) 63 { 64 scanf("%s",s); 65 printf("Test case #%d\n",k++); 66 getnext(); 67 for(int i=1; i<=n; i++) 68 { 69 if( i!=(i-next[i]) &&! (i%(i-next[i]) )) 70 printf("%d %d\n",i, i/(i-next[i]) ); 71 } 72 Prs(""); 73 } 74 return 0; 75 }
emmmmm 我把输出中的“Test”写成了“Text”,调了一下午,一直wa,愣是没发现,简直怀疑人生了。