KMP
Algorithm Desciption
KMP算法是一个用于解决A串是否是B串的子串的问题。这个算法的核心在于当出现不匹配的状态的时候,并不是直接跳回到0的位置上面去,而是去寻找这个已匹配的串中,前缀和后缀相等的长度。(当然如果前缀和后缀不相等,还是0)
用图来解释比如说现在失配了(1,2,3,4这四个段完全相同)
然后就这么跳
图画的丑,不要在意
而怎么跳呢,就需要自己去处理出一个Nxt数组了
Description
给定若干长度小于等于1000000的字符串,询问每个字符串最多由多少个相同的子串重复连接而成(循环节),例如ababab,最多由3个ab连接而成
Input
若干行,每行一个字符串。最后一行是一个"."点号,作为输入的结尾
Output
对应输入的每行,计算最多有多少个相同子串连接而成
Sample Input
abcd
aaaa
ababab
.
Sample Output
1
4
3
Analysis
这一道题直接来看的话好像和KMP算法没有什么关系,但是通过KMP算法确实是可以做这一道题的。
对于输入的字符串,它的Nxt值有两种结果
1.最后一个数的前缀长度加上后缀长度大于他自己的长度。这意味着它最长的相同的前缀后缀之间有重叠的地方,如图
这样的话,就容易得出答案为\(t\div(t-Nxt[t-1])\)(t是字符串的长度)
2.如果说没有重合,那么就直接是1就好了
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000002
using namespace std;
char c[maxn];
int k[maxn];
void init();
int main(){
scanf("%s",c);
while(c[0]!='.'){
init();
int t=strlen(c);
if(!(t%(t-k[t-1])))printf("%d\n",t/(t-k[t-1]));
else printf("1\n");
scanf("%s",c);
}
}
void init(){
int t=strlen(c);
k[0]=0;
for(int i=1,j=0;i<t;i++){
while(j>0&&c[i]!=c[j])j=k[j-1];
if(c[i]==c[j])j++;
k[i]=j;
}
}
我不求被他人理解,被理解类似于自我卖淫