求子串在主串中的位置:
#include <iostream> //kmp
#include <string>
#include <cstring> //首先是返回字串所在的位置。
#include <algorithm>
using namespace std;
const int inf=1e6+7;
int next[inf];
void getnext(string str2,int m) //当str1[i]!=str2[j]时,next[j]是下一个要移动的位置。也就是k。
{
next[0]=-1;
int k=-1; //和next【0】是对应的。
int j=0; //指向第一个位置。
while(j<m)
{
if(k==-1||str2[k]==str2[j])
{
if(str2[++j]==str2[++k])
next[j]=next[k];
else
next[j]=k; //只要对应起来就行。
}
else
{
k=next[k];
}
}
}
int kmp(string str1,int n,string str2,int m) //返回的是确定的位置吧。
{
int i=0; //指向的是str1.
int j=0; //指向的是str2.
while(i<n&&j<m)
{
if(j==-1||str1[i]==str2[j])
{
i++;
j++;
}
else
j=next[j];
}
if(j==str2.length())
return i-j;
else
return -1;
}
int main()
{
string str1,str2; //str1是主串(n)。str2是子串(m)。
while(cin>>str1>>str2)
{
memset(next,0,sizeof(next));
getnext(str2,str2.length());
int ans=kmp(str1,str1.length(),str2,str2.length());
cout<<ans<<endl;
}
return 0;
}
求子串在主串中出现的次数:
#include <iostream> //kmp
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=1e6+7;
int next1[inf];
void getnext(string str2,int m) //当str1[i]!=str2[j]时,next[j]是下一个要移动的位置。也就是k。
{
next1[0]=-1;
int k=-1; //和next【0】是对应的。
int j=0; //指向第一个位置。
while(j<m)
{
if(k==-1||str2[k]==str2[j])
{
if(str2[++j]==str2[++k])
next1[j]=next1[k];
else
next1[j]=k; //只要对应起来就行。
}
else
{
k=next1[k];
}
}
}
int kmp(string str1,int n,string str2,int m) //返回的是确定的位置吧。
{
int i=0; //指向的是str1.
int j=0; //指向的是str2.
int ans=0;
while(i<n)
{
if(j==-1||str1[i]==str2[j])
{
i++;
j++;
}
else
j=next1[j];
if(j==m)
{
ans++;
j=next1[j]; //还有这里。 or j=next1[j-1];
// i--; //这里
}
}
return ans;
}
int main()
{
string str1,str2; //str1是主串(n)。str2是子串(m)。
while(cin>>str1>>str2)
{
memset(next1,0,sizeof(next1));
getnext(str2,str2.length());
int ans=kmp(str1,str1.length(),str2,str2.length());
cout<<ans<<endl;
}
return 0;
}