18940 最小循环节(KMP算法)
Description
给定一个字符串,请计算这个字符串最多是由多少个相同的子字符串重复连接而成的。
如:acacac 最多有 3 个 ac 连接而成,bbbb最多由4个b连接而成,abc最多由1个abc连接而成。
此问题需求出整个字符串的最大相同真前后缀,需使用kmp算法或字符串哈希法,具体解释可看下图或百度最小循环节。
输入格式
一个字符串,长度不超过100000。
输出格式
组成字符串的最多重复连接子串的个数。
输入样例
ababab
输出样例
3
解题思路:
求next数组,最大相同前后缀长度p = next[len]
#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std;
char s[1000001];
int Next[1000001] = {0};
int len,p;//p:整个字符串最大相同前缀的长度
//定义模式串s的next函数值并存入数组next
void getNext()
{
//注意字符串是从下标1开始录入,下标0用来存放长度
int k = 0;
Next[1] = 0;//初始化也是初始化下标为1的next
for(int i = 2;i <=len;i++){ //i是字符串的下标,k是next的下标
while(k && s[k+1] != s[i]) k=Next[k];
if(s[k + 1] == s[i]){ //k这里有下标和当前next的值两个意思
k++;
Next[i] = k;
}
}
}
int main()
{
scanf("%s",s + 1);//字符串从第二位输入(s[1]开始)//相当于cin >> s+1;
len = strlen(s+1);
getNext();
p = Next[len];//p长度
int m = len - p;
if(len % m == 0){ //[1,m]和[m+1,2m]相同,同理得整个字符串为长度为m的循环子串获得的
//循环次数
int ans = len / m;
cout << ans << endl;
}
else{
cout << "1" << endl;
}
return 0;
}