模板:
#define LL long long
#define MS(a,b) memset(a,b,sizeof(a))
#define FI(a,b) fill(a,a+maxn,b)
#define sf(n) scanf("%d",&n)
#define sf2(a,b) scanf("%d%d",&a,&b)
#define pf(n) printf("%d\n",n)
#define ffr(i,n) for(i=0;i<n;i++)
/*
s:abcdabcadcabcdcab
p: abcdcab
next:-1000001
*/
using namespace std;
void getNext(const std::string& p, std::vector<int>& ne)
{
ne.resize(p.size());
ne[0] = -1;
int i = 0, j = -1;
while (i != p.size() - 1)
{
if (j == -1 || p[i] == p[j])
{
++i;
++j;
ne[i] = j;
}
else
{
j = ne[j];
}
}
}
int kmp(const std::string& s, const std::string& p, const int sIndex = 0)//返回下标 从0开始
{
std::vector<int>ne(p.size());
getNext(p, ne);//获取next数组,保存到vector中
int i = sIndex, j = 0;
while(i != s.length() && j != p.length())
{
if (j == -1 || s[i] == p[j])
{
++i;
++j;
}
else
{
j = ne[j];
}
}
return j == p.length() ? i - j: -1;
}
int main()
{
string a,b;
while(cin>>a>>b){
cout<<kmp(a,b,0)<<endl;//返回匹配的下标
}
return 0;
}
hdu1686 模型:统计字串在母串中出现的次数(字母可重复)
#include <stdio.h>
#include <string.h>
int next[10005];
char str1[1000005],str2[10005];
int cnt;
void get_next(int len2)//生成next数组
{
int i = 0,j = -1;
next[0] = -1;
while (i<len2)
{
if(j == -1 || str2[i] == str2[j])
{
i++;
j++;
if (str2[i]!=str2[j])
next[i] = j;
else
next[i] = next[j];
}
else
j = next[j];
}
}
int kmp(int len1,int len2)//kmp算法
{
int i=0,j=0;
get_next(len2);
while(i<len1)
{
if(j==-1||str1[i]==str2[j])
{
++i;
++j;
}
else
j=next[j];
if(j == len2)
{
cnt++;
j = next[j];
}
}
}
int main()
{
int n;
int len1,len2;
scanf("%d",&n);
getchar();
while(n--)
{
gets(str2);
gets(str1);
len1 = strlen(str1);
len2 = strlen(str2);
cnt = 0;
kmp(len1,len2);
printf("%d\n",cnt);
}
return 0;
}
next数组应用:前缀个数 以下标i为终点重复子串的个数
aabaabaabaab
2 26 29 312 4
void getNext(const std::string& p, std::vector<int>& next)
{
next.resize(p.size()+1);
next[0] = -1;
int i = 0, j = -1;
while (i != p.size())
{
if (j == -1 || p[i] == p[j])
{
++i;
++j;
next[i] = j;
if(i%(i-next[i])==0&&i/(i-next[i])>1){
printf("%d %d\n",i,i/(i-next[i]));
}
}
else
{
j = next[j];
}
}
}
int main()
{
int n,i,Case=1;
char s[maxn];
while(~sf(n)&&n){
scanf("%s",s);
vector<int>next(strlen(s)+1);
printf("Test case #%d\n",Case++);
getNext(s, next);
printf("\n");
}
return 0;
}
循环节:
#include<iostream>
#include<string.h>
using namespace std;
int next[1000005];
char s[1000005];
void getnext()
{
int i=0,j=-1;
next[0]=-1;
int len=strlen(s);
while(i<len)
{
if(s[i]==s[j]||j==-1)
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
while(scanf("%s",s)>0)
{
if(s[0]=='.')
break;
int len=strlen(s);
getnext();
if(len%(len-next[len])==0)
printf("%d\n",len/(len-next[len]));
else
printf("1\n");
}
return 0;
}