KMP算法
1. 题意:求字符串的最大周期
2. 反正我是没想到用KMP做。。。。,看了题解好久都没有反应过来。。。。,继续看了不少KMP算法的资料,脑残儿童总算开窍了一点
3. 其实本题是利用了KMP算法中next数组的特性来求解,因为在KMP算法中表示的是当前字符串的最长相同前后缀的长度,不过还要整个数组向右移动一位,next[0]变为-1,所以就可以用KMP求出当前字符串的最长相同前后缀的长度。
接下来的问题就是如何用最长相同前后缀的长度求最大周期,举个例子吧
s | a | b | a | b | a | b |
next | -1 | 0 | 0 | 1 | 2 | 3 |
要用的 | 0 | 0 | 1 | 2 | 3 | 4 |
子串 | 最长公共前后缀 | 长度 |
a | 空 | 0 |
ab | 空 | 0 |
aba | a | 1 |
abab | ab | 2 |
ababa | aba | 3 |
ababab | abab | 4 |
看到这个表大家可能就会有点感觉了,sublen=n-next[n]就可以求出重复串的长度(如果它存在的话),如果n%sublen == 0, 就可以说明它的确是重复字串。
还有需要特别注意的就是网上有一个优化过的求next的算法,用那个的话求出来结果就不一定对了,因为它并不会对应最长相同前后缀。
附上了一个讲得比较详细的KMP算法链接
http://blog.csdn.net/v_july_v/article/details/7041827
附代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 1000010
using namespace std;
char s[N];
int next[N];
int len;
void getnext()
{
int j=0;
int k=-1;
next[0]=-1;
while(j < len)
{
if(k == -1 || s[k] == s[j])
{
++k;
++j;
next[j]=k;
}
else
{
k=next[k];
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
while(1)
{
scanf("%s",s);
len=strlen(s);
if(len <= 1)
{
break;
}
getnext();
if(next[len] > 0 &&len % (len-next[len]) == 0)
{
printf("%d\n",len/(len-next[len]));
}
else
{
printf("1\n");
}
}
return 0;
}