地址:http://codeforces.com/contest/1029/problem/A
KMP算法求字符串的最小循环节
KMP最小循环节、循环周期:
定理:假设S的长度为len,则S存在最小循环节,循环节的长度L为len-next[len],子串为S[0…len-next[len]-1]。
(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。
(2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。
算法理解:https://blog.csdn.net/hao_zong_yin/article/details/77455285
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 2 * 1e5 + 5;
#define fi first
#define se second
int nextnum[500];
int main()
{
string s;
int step=1,n,k;
cin >> n >> k;
cin >> s;
if(k == 1){
cout << s << endl;
return 0;
}
int len=s.size();
memset(nextnum,0,sizeof(0));
int i=0,j=1;
while(j<len) //先写出next数组
{
if(s[i]!=s[j]&&i!=0)
{
i=nextnum[i-1];
}
else if(s[i]!=s[j]&&i==0)
{
nextnum[j]=0;
j++;
}
else if(s[i]==s[j])
{
nextnum[j]=i+1;
j++,i++;
}
}
int l = len - nextnum[len-1];
string x = s.substr(0,l);
//cout << x << endl;
int num = (len + l - 1) / l;
//cout << num << endl;
//处理开头
for(int i = 0;i < num;++i)
{
cout << x;
}
for(int i = 1;i < k - 1;++i)
{
cout << x;
}
//处理结尾
if(len % l == 0){
//循环节长度为len
cout << x;
}else{
int ans = l - len % l;
//cout << ans << endl;
for(int i = 0;i < x.size() - ans;++i)
cout << x[i];
}
cout << endl;
return 0;
}