Description
S[i]=S[i+P] for i in [0..SIZE(S)-p-1],
then the prefix is a “period” of S. We want to all the periodic prefixs.
Input
The first line contains an integer T representing the number of cases. Then following T cases.
Each test case contains a string S (1 <= SIZE(S) <= 1000000),represents the title.S consists of lowercase ,uppercase letter.
Output
Sample Input
4 ooo acmacmacmacmacma fzufzufzuf stostootssto
Sample Output
Case #1: 3 1 2 3 Case #2: 6 3 6 9 12 15 16 Case #3: 4 3 6 9 10 Case #4: 2 9 12
参考代码:
#include <cstdio>
#include <cstring>
const int maxn = 1000010;
int p[maxn],ans[maxn];
char str[maxn]; //保存字符串的数组
void get_p(int len){
p[1] = 0;
int j = 0;
for(int i = 2;i <= len;i++){
while(j > 0 && str[j+1] != str[i]) j = p[j];
//这个循环是当结果失配时才使用的
if(str[j+1] == str[i]) j++;
p[i] = j;
}
}
int main(){
int nkase;
scanf("%d",&nkase);
for(int kase = 1;kase <= nkase;kase++){
scanf("%s",str+1);
// 这个+1表示的含义是从下标为1的地方开始输入,方便后续的操作
//像C中这样控制字符串输入的格式还是非常方便的
int len = strlen(str+1);
get_p(len);
//这个是单单初始化了数组p得到了结果,然后主要的思想未知,可能是在求解next数组
//将str的长度告诉函数,通过匹配的方式得到数组p,相当于next数组
int t = p[len],cnt = 0;
while(t){
ans[cnt++] = len-t;
t = p[t];
//每次取到的数值是一定会比以前的要小,所以这不可能是一个死循环的
}
ans[cnt++] = len;
//在这里将所有的运算结果全部保留下来,包括数量cnt和最后输出的结果ans[];
printf("Case #%d: %d ",kase,cnt);
//在这里有两个参数,即运行的次数和返回的结果数
for(int i = 0;i < cnt-1;i++) printf("%d ",ans[i]);
printf("%d ",ans[cnt-1]);
}
return 0;
}
关键点分析:
本题还是要先找到next数组,然后通过next数组来访问求解。
当然,每个next数组保存的内容都是不一样的,都是前一个字符匹配得到的信息结果保留在那个地方。
//KMP的算法重点就是求解next数组,当求解next数组时要知道关键点就是next数组中保存的数据是什么意思,那是当失配的时候后缀部分和前面的部分是否相同的表现