const int maxn=1e6+5;
int nx[maxn];
// nx[] 的含义:x[i-nx[i]...i-1]=x[0...nx[i]-1]
// nx[i] 为满足 x[i-z...i-1]=x[0...z-1] 的最大 z 值(就是 x 的自身匹配)
void getnx(char *x) {
int i,j;
int m=strlen(x);
j=nx[0]=-1;
i=0;
while (i<m) {
while ( -1!=j && x[i]!=x[j]) j=nx[j];
nx[++i]=++j;
}
}
//输出多次出现的位置
void kmp(char *x, char *y) { //x为匹配串,y为模式串
int n=strlen(x);
int m=strlen(y);
int i=0,j=0;
getnx(y);
while (i<n && j<m) {
while (-1!=j && x[i]!=y[j]) j=nx[j];
i++;
j++;
if (j==m) {
cout<<i-j+1<<endl;
j=nx[j];
}
}
}
//输出第一次出现的位置
int kmp(char *x, char *y) { //x为匹配串,y为模式串
int n=strlen(x);
int m=strlen(y);
int i=0,j=0;
getnx(y);
while (i<n && j<m) {
while (-1!=j && x[i]!=y[j]) j=nx[j];
i++;
j++;
}
if (j==m)
return i-j;
else return -1;
}
//返回y在x中出现的次数,可以重叠
int kmp_count(char *x, char *y){
int n=strlen(x);
int m=strlen(y);
int i=0,j=0,ans=0;
getnx(y);
while (i<n){
while (-1!=j && x[i]!=y[j]) j=nx[j];
i++;
j++;
if (j>=m){
ans++;
j=nx[j]; //如果不可重叠,将此处改为 j=0;
}
}
return ans;
}
//输出nx数组
int len=strlen(y);
for (int i=1; i<=len; i++)
cout<<nx[i]<<" ";
扩展kmp算法模版
const int maxn=1e6+5;
int nx[maxn];
int extend[maxn];
//nx[i]: y[i...m-1] 与 y[0...m-1] 的最长公共前缀
//extend[i]: x[i...n-1] 与 y[0...m-1] 的最长公共前缀
void getnx_ex(char *x){
int m=strlen(x);
nx[0]=m;
int j=0,k=1;
while (j+1<m && x[j]==x[j+1]) j++;
nx[1]=j;
for (int i=2; i<m; i++){
int p=nx[k]+k-1;
int l=nx[i-k];
if (i+l<p+1) nx[i]=l;
else {
j=max(0,p-i+1);
while (i+j<m && x[i+j]==x[j]) j++;
nx[i]=j;
k=i;
}
}
}
void exkmp(char *x, char *y){
getnx_ex(y);
int n=strlen(x);
int m=strlen(y);
int j=0,k=0;
while (j<m && j<n && x[j]==y[j]) j++;
extend[0]=j;
for (int i=1; i<n; i++){
int p=extend[k]+k-1;
int l=nx[i-k];
if (i+l<p+1) extend[i]=l;
else {
j=max(0,p-i+1);
while (i+j<n && j<m && x[i+j]==y[j]) j++;
extend[i]=j;
k=i;
}
}
}
//输出nx数组
int len=strlen(y);
for (int i=0; i<len; i++)
cout<<nx[i]<<" ";
KMP循环节问题
HDU 3746
如果一个字符串为循环串时,(例如adcabcabc)那么它的next[]数组满足下面性质:
1、len%(len-nx[len])==0;
2、len/(len-nx[len])就是循环的次数
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int nx[maxn];
void getnx(char *x) {
int i,j;
int m=strlen(x);
j=nx[0]=-1;
i=0;
while (i<m) {
while ( -1!=j && x[i]!=x[j]) j=nx[j];
nx[++i]=++j;
}
}
char s[maxn];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin>>T;
while (T--){
memset(nx,0,sizeof(nx));
cin>>s;
getnx(s);
int len=strlen(s);
int same=len-nx[len]; //循环节的长度
if (nx[len]==0) cout<<len<<endl;
else if (len%same==0) cout<<0<<endl;
else cout<<same-len%same<<endl;
}
return 0;
}