【KMP】Radio Transmission(最小循环子串)
Description
给你一个字符串,它是由某个字符串不断自我连接形成的。但是这个字符串是不确定的,现在只想知道它的最短长度是多少。
Input
第一行给出字符串的长度L,第二行给出一个字符串,全由小写字母组成。
Output
输出最短的长度。
Samples
Input
8
cabcabca
Output
3
Hint
我们可以利用abc不断自我连接得到abcabcabc,读入的cabcabca是它的子串。
对于全部数据,1≤L≤1e6
思路:KMP核心算法
对一个长度为n的字符串来说,nextt[n]记录的是该字符串最长的相同前缀与后缀,也就是说有nextt[n]的长度是重复出现的,那么减去这个前缀以后,剩下的就是这个字符串最小的循环节了,即n-nextt[n]即我们所要的答案。
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
string s;
int n;
int nextt[N];
void getnext(){
int i = 0; //主串
int j = -1;//子串
nextt[0] = -1;
while(i<n){
if(j == -1 || s[i]==s[j]){
i++;
j++;
nextt[i] = j;
}
else{
j = nextt[j];
}
}
}
int main(){
cin>>n>>s;
getnext();
int ans = n-nextt[n];
cout <<ans<< endl;
return 0;
}
也可以直接在主函数操作:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int nextt[maxn];
char s[maxn];
int cnt=0;
int main(){
int i,j,k;
int n;
cin>>n;
scanf("%s",s+1);
j=0;
for(i=2;i<=n;i++){
while(s[i]!=s[j+1]&&j){
j = nextt[j];
}
if(s[i]==s[j+1]){
j++;
}
nextt[i] = j;
}
int ans = n-nextt[n];
cout<<ans;
return 0;
}