模板
#include <cstdio>
#include <cstring>
using namespace std;
int n;
char ts[100];
char ms[100];
int next[100];
int len;
void getNext()
{
int i = 0, j = -1;
next[0] = -1;
while (i != len){
if (j == -1 || ts[i] == ts[j]){
next[++i] = ++j;
}
else
j = next[j];
}
}
int KmpMatch(char ms[], char ts[])
{
int tlen = strlen(ts);
for(int i = 0, j = 0; ms[i];)
{
if(j == -1 || ms[i] == ts[j])
{
if(j == tlen - 1)
return i - tlen + 1;
else
i++, j++;
}
else
j = next[j];
}
return -1;
}
Next数组的各种操作
看案例意会即可
if (len % (len - nxt[len]) == 0)
printf("%d\n", len - nxt[len]);
2
abcabcabcabc
-1000123456789
能求到next[n]这一位。
既然要求三个相同的子串,而且有两个还必须在开头和结尾,那就求Next数组,Next数组存的是前后缀相同的长度,所以只需要找【2*i,L-Next[i]】之间相同的字串,即Next[j]==i;
-
找循环串的每一个结束
while(nex[len] != 0) { q.push(nex[len]); len = nex[len]; } while(!q.empty()) { printf("%d ",q.top()); q.pop(); }
-
补全循环串的最小个数
(len -nex[len]) -len %(len-nex[len])
KmpMatch函数里的各种操作
-
求有多少个可分开的子串
int KmpMatch(char ms[],char ts[]) { BuildNext( ts); int tlen = strlen(ts); for(int i = 0,j = 0; ms[i]; ) { if(j == -1 || ms[i] == ts[j]) { //这一段是关键 if(j == tlen-1 ) { con++; j = 0; i++; } else i++,j++; } else j = nex[j]; } return -1; }
-
求有多少个可以重复的子串
int KmpMatch(char ms[],char ts[]) { int cnt = 0; int tlen = strlen(ts); for(int i = 0,j = 0; ms[i]; ) { if(j == -1 || ms[i] == ts[j]) { i++; j++; if(j == tlen) { //这里是关键 j = nex[j]; cnt ++; } } else j = nex[j]; } return cnt; }
例题
Uva 445 Periodic Strings
#include <cstdio>
#include<iostream>
#include <cstring>
using namespace std;
char str[100];
int nxt[100];
int len;
void getNext()
{
int i = 0, j = -1;
nxt[0] = -1;
while (i != len){
if (j == -1 || str[i] == str[j]){
nxt[++i] = ++j;
}
else
j = nxt[j];
}
}
int main()
{
scanf("%d", &n);
while (n--){
scanf("%s", str);
len = strlen(str);
getNext();
if (len % (len - nxt[len]) == 0)
printf("%d\n", len - nxt[len]);
else
printf("%d\n", len);
if (n)
printf("\n");
}
return 0;
}
hdu 剪花布条
#include<cstdio>
#include<cstring>
using namespace std;
int nex[100000];
int con;
void BuildNext(char ts[])
{
nex[0] = -1;
for(int i = 0, j = -1;ts[i]; )
{
if(j == -1 || ts[i] == ts[j])
nex[++i] = ++j;
else j = nex[j];
}
}
int KmpMatch(char ms[],char ts[])
{
BuildNext( ts);
int tlen = strlen(ts);
for(int i = 0,j = 0; ms[i]; )
{
if(j == -1 || ms[i] == ts[j])
{
if(j == tlen-1 )
{
con++;
j = 0;
i++;
}
else
i++,j++;
}
else
j = nex[j];
}
return -1;
}
int main()
{
char ms[10000];
char ts[10000];
while(scanf("%s",&ms))
{
if(ms[0] =='#') return 0;
scanf("%s",&ts);
con = 0;
KmpMatch(ms,ts);
printf("%d\n",con);
}
}
hdu 4847 Wow!Such Doge!
#include<iostream>
#include<cstdio>
#include<cstring>
int doge[10];
int dogE[10];
int doGe[10];
int doGE[10];
int dOge[10];
int dOgE[10];
int dOGe[10];
int dOGE[10];
int Doge[10];
int DogE[10];
int DoGe[10];
int DoGE[10];
int DOge[10];
int DOgE[10];
int DOGe[10];
int DOGE[10];
void Buildnext(int as[],const char ts[])
{
as[0] = -1;
for(int i = 0, j = -1; ts[i]; )
{
if(j == -1 || ts[i] == ts[j])
as[++i] = ++j;
else j = as[j];
}
}
void init_next()
{
Buildnext(doge,"doge");
Buildnext(dogE,"dogE");
Buildnext(doGe,"doGe");
Buildnext(doGE,"doGE");
Buildnext(dOge,"dOge");
Buildnext(dOGe,"dOGe");
Buildnext(dOGE,"dOGE");
Buildnext(Doge,"Doge");
Buildnext(DogE,"DogE");
Buildnext(DoGe,"DoGe");
Buildnext(DoGE,"DoGE");
Buildnext(DOge,"DOge");
Buildnext(DOgE,"DOgE");
Buildnext(DOGe,"DOGe");
Buildnext(DOGE,"DOGE");
Buildnext(dOgE,"dOgE");
}
int KmpMatch(char ms[], int nex[], const char ts[])
{
int cnt = 0;
for(int i = 0,j = 0;ms[i]; )
{
if(j == -1 || ms[i] == ts[j])
{
i++;
j++;
}
else j = nex[j];
if(j == strlen(ts))
{
cnt++;
j = 0;
}
}
return cnt;
}
int main()
{
int cnt = 0;
char s1[100000];
init_next();
while(scanf("%s",&s1)!= EOF)
{
cnt +=KmpMatch(s1,doge,"doge")+KmpMatch(s1,dogE,"dogE")+KmpMatch(s1,doGe,"doGe")+KmpMatch(s1,doGE,"doGE");
cnt +=KmpMatch(s1,dOge,"dOge")+KmpMatch(s1,dOgE,"dOgE")+KmpMatch(s1,dOGe,"dOGe")+KmpMatch(s1,dOGE,"dOGE");
cnt +=KmpMatch(s1,Doge,"Doge")+KmpMatch(s1,DogE,"DogE")+KmpMatch(s1,DoGe,"DoGe")+KmpMatch(s1,DoGE,"DoGE");
cnt +=KmpMatch(s1,DOge,"DOge")+KmpMatch(s1,DOgE,"DOgE")+KmpMatch(s1,DOGe,"DOGe")+KmpMatch(s1,DOGE,"DOGE");
}
printf("%d\n",cnt);
}
hdu 1686、poj 3461 Oulipo
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int nex[1000000];
void Buildnext(char ts[])
{
nex[0] = -1;
for(int i = 0,j = -1; ts[i]; )
{
if(j == -1 ||ts[i] == ts[j])
nex[++i] = ++j;
else j = nex[j];
}
}
int KmpMatch(char ms[],char ts[])
{
int cnt = 0;
int tlen = strlen(ts);
for(int i = 0,j = 0; ms[i]; )
{
if(j == -1 || ms[i] == ts[j])
{
i++;
j++;
if(j == tlen)
{
j = nex[j];
cnt ++;
}
}
else j = nex[j];
}
return cnt;
}
int main()
{
int t;
cin>>t;
while(t--)
{
char ts[10000000], ms[10000000];
scanf("%s %s",&ts,&ms);
Buildnext(ts);
printf("%d\n", KmpMatch(ms,ts));
}
}
hdu 1711 Number Sequence
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int ts[1000000], ms[1000000];
int nex[1000000];
void Buildnext(int ts[],int len2)
{
nex[0] = -1;
for(int i = 0,j = -1; i<=len2; )
{
if(j == -1 ||ts[i] == ts[j])
nex[++i] = ++j;
else j = nex[j];
}
}
int KmpMatch(int ms[],int ts[],int tslen, int len)
{
int cnt = 0;
int tlen = tslen;
for(int i = 0,j = 0; i<len; )
{
if(j == -1 || ms[i] == ts[j])
{
i++,j++;
}
else j = nex[j];
if(j == tlen )
{
return i- tlen + 1;
}
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int len,len2;
scanf("%d%d",&len,&len2);
for(int i = 0;i<len; i++) scanf("%d",&ms[i]);
for(int i = 0;i<len2; i++) scanf("%d",&ts[i]);
Buildnext(ts,len2);
int ans = KmpMatch(ms,ts,len2, len);
printf("%d\n",ans);
}
}
hdu 4763 Theme Section(参考)
思路:
既然要求三个相同的子串,而且有两个还必须在开头和结尾,那就求Next数组,Next数组存的是前后缀相同的长度,所以只需要找【2*i,L-Next[i]】之间相同的字串,即Next[j]==i;
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1000005;
char s[N];
int Next[N],l;
void get_Next()
{
int i=0,j=-1;
Next[0]=-1;
while(i<l)
{
if(j==-1||s[i]==s[j])
Next[++i]=++j;
else
j=Next[j];
}
}
int KMP()
{
int i,j;
for(i=Next[l]; i; i=Next[i])
for(j=2*i; j<=l-i; j++)
if(Next[j]==i)
return i;
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
int ans=0,k,i,j;
l=strlen(s);
get_Next();
// for(i=1; i<=l; i++)
// printf("%d ",Next[i]);
// printf("\n");
printf("%d\n",KMP());
}
return 0;
}
参考:https://blog.csdn.net/qq_41984014/article/details/81626493?ops_request_misc=&request_id=&biz_id=102&utm_term=theme%20section&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-81626493.nonecase&spm=1018.2226.3001.4187
poj 2046 Power Strings
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int nex[1000005];
char ms[1000005];
int cnt;
void BuildNext()
{
nex[0] = -1;
for(int i =0,j = -1;ms[i]; )
{
if(j == -1 || ms[i] == ms[j])
nex[++i] = ++j;
else j = nex[j];
}
}
int main()
{
int cyc;
while(scanf("%s",&ms)!= EOF && strcmp(ms,".") != 0 )
{
BuildNext();
int len = strlen(ms);
cyc = len - nex[len];
if(len %cyc == 0)
printf("%d\n", len /cyc);
else
printf("1\n");
}
return 0;
}
poj 2752 Seek the Name, Seek the Fame
#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
int nex[1000000];
char ms[1000000];
int cnt;
void BuildNext()
{
nex[0] = -1;
for(int i =0,j = -1;ms[i]; )
{
if(j == -1 || ms[i] == ms[j])
nex[++i] = ++j;
else j = nex[j];
}
}
int main()
{
while(scanf("%s",&ms) != EOF)
{
stack<int>q;
int len = strlen(ms);
BuildNext();
q.push(len);
while(nex[len] != 0)
{
q.push(nex[len]);
len = nex[len];
}
while(!q.empty())
{
printf("%d ",q.top());
q.pop();
}
printf("\n");
}
}
poj 2185 Milking Grid (难题)
#include<iostream>
#include<cstring>
#include<iostream>
using namespace std;
char cow[10010][80];
char rvercow[80][10010];
int nexrow[10010];
int nexcol[10010];
int row,col;
void getnexrow()
{
int j = -1,k = 0;
nexrow[0] = -1;
while(k < row)
{
if(j == -1 || !strcmp(cow[k],cow[j]))
{
k++;
j++;
nexrow[k] = j;
}
else j = nexrow[j];
}
}
void getnexcol()
{
int j = -1,k = 0;
nexcol[0] = -1;
while(k < col)
{
if(j == -1 ||!strcmp(rvercow[k],rvercow[j]))
{
j++,k++;
nexcol[k] = j;
}
else
j = nexcol[j];
}
}
int main()
{
while(cin>>row>>col)
{
for(int i =0;i < row;i++)
cin>>cow[i];
getnexrow();
for(int i =0; i<row; i++)
for(int j = 0; j<col; j++)
rvercow[j][i] = cow[i][j];
getnexcol();
int minn = (row - nexrow[row]) * (col - nexcol[col]);
cout<<minn<<endl;
}
return 0;
}
poj 3080 Blue Jeans
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int nex[1000000];
void BuildNex(string t)
{
nex[0] = -1;
int i = 0,j = -1;
int len = t.length();
while(i <len)
{
if(j == -1 || t[i] == t[j])
{
nex[++i] = ++j;
}
else j = nex[j];
}
}
int kmp(string s,string t)
{
int i = 0, j = 0;
int lens = s.length(),lent = t.length();
while(i < lens && j <lent)
{
if(j == -1 || s[i] == t[j])
i++,j++;
else j = nex[j];
if(j == lent)
return i-j+1;
}
return -1;
}
int main()
{
int nn;
scanf("%d",&nn);
string s[15];
while(nn--)
{
int n;
cin>>n;
for(int i = 0; i<n;i++) cin>>s[i];
string t;
string res;
int ma = 0;
for(int i = 0;i < 60;i++)
{
for(int j = i+1; j<= 60;j++)
{
t = string(s[0].begin()+i,s[0].begin()+j);
BuildNex(t);
int f = 0;
for(int k = 1;k<n; k++)
{
if(kmp(s[k],t) == -1)
{
f = 1;
break;
}
}
if(!f)
{
if(ma<= j-i)
{
if(ma<j-i) res = t;
else res = min(res,t);
ma = j - i;
}
}
}
}
if(ma <3) printf("no significant commonalities\n");
else
cout<<res<<endl;
}
}
hdu 1358 Period
#include<cstdio>
#include<iostream>
using namespace std;
int nex[1000005];
char ts[1000005];
void Buildnex(char ts[])
{
nex[0] = -1;
for(int i = 0, j = -1;ts[i]; )
{
if(j == -1 || ts[i] == ts[j])
nex[++i] = ++j;
else j = nex[j];
}
}
int times;
int main()
{
int t;
times = 0;
while(scanf("%d",&t)!=EOF)
{
if(t == 0)
return 0;
times++;
scanf("%s",ts);
Buildnex(ts);
printf("Test case #%d\n",times);
for(int i = 2;i<=t;i++)
{
if(i%(i-nex[i]) == 0 && i/(i-nex[i]) > 1)
{
cout<<i<<" "<<i/(i-nex[i])<<endl;
}
}
cout<<endl;
}
}
hdu 3746 Cyclic Nacklace
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int nex[1000005];
char ts[1000005];
void Buildnex(char ts[])
{
nex[0] = -1;
for(int i =0,j = -1;ts[i]; )
{
if(j == -1 || ts[i] == ts[j])
{
nex[++i] = ++j;
}
else j = nex[j];
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%s",&ts);
Buildnex(ts);
int len = strlen(ts);
if(len % (len -nex[len]) == 0 && len != (len -nex[len]))
cout<<0<<endl;
else
cout<<(len -nex[len]) -len %(len-nex[len])<<endl;
}
}