fzu 1901 next+脑洞
题目大意:
给你一个字符串str,对于每个str长度为p的前缀,如果str[i]==str[p+i](p+i<len),那么我们认为它是一个periodic prefixs.求所有满足题意的前缀的长度p
基本思路:
•KMP算法中next数组的含义是什么?
•next数组:失配指针
•如果目标串的当前字符i在匹配到模式串的第j个字符时失配,那么我们可以让i试着去匹配next(j)
•对于模式串str,next数组的意义就是:
•如果next(j)=t,那么str[1…t]=str[len-t+1…len]
•我们考虑next(len),令t=next(len);
•next(len)有什么含义?
•str[1…t]=str[len-t+1…len]
•那么,长度为len-next(len)的前缀显然是符合题意的。
•接下来我们应该去考虑谁?
•t=next( next(len) );
•t=next( next (next(len) ) );
• 一直下去直到t=0,每个符合题意的前缀长是len-t
代码如下:
#include<stdio.h> #include<string.h> #include<algorithm> #include<stdlib.h> using namespace std; const int N = 1e6+7; char s[N]; int Next[N], ans[N]; void GetNext(char a[], int n) { int i=0, j=-1; Next[0] = -1; while(i<n) { if(j==-1 || a[i]==a[j]) Next[++i] = ++j; else j = Next[j]; } } int main() { int T, t=1, k, len; scanf("%d", &T); while(T--) { scanf("%s", s); len = strlen(s); GetNext(s, len); k = 0; for(int j=len; j>0; j=Next[j]) ans[k++] = len - Next[j]; printf("Case #%d: %d\n", t++, k); for(int i=0; i<k; i++) printf("%d%c", ans[i], i==k-1?'\n':' '); } return 0; }