KMP算法
1.寻找最长前缀后缀
如果给定的模式串是:“ABCDABD”,从左至右遍历整个模式串,求出最长前缀后缀
2.求next数组
next 数组考虑的是除当前字符外的最长相同前缀后缀,所以通过第①步骤求得各个前缀后缀的公共元素的最大长度后,只要稍作变形即可:将第①步骤中求得的值整体右移一位,然后初值赋为-1
3.进行匹配
根据最大长度表求出了next 数组后,从而有失配时,模式串向右移动的位数为:
失配字符所在位置 – 失配字符对应的next 值也就是j-next[j]。
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int Next[10001];
//求KMP的Next数组
void GetNext( string p)
{
int i=0;
int j=-1;
Next[i]=j;
while(i<p.size())
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
if(i==p.size()||p[i]!=p[j])
Next[i]=j;
else
Next[i]=Next[j];
}
else
{
j=Next[j];
}
}
}
//S为母串,p为匹配子串,如果匹配返回匹配位置,否则返回-1
int KMP(string s, string p)
{
GetNext(p);//求得Next数组
int i=0;//在S串中的下标
int j=0;//在P串中的下标
int count=0;//匹配串出现的次数
while(i<s.size())
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else if(j<p.size())
j=Next[j];
if(j==p.size())
{
count++;
j=Next[p.size()];
}
}
return count;
}
int main()
{
string str1;
string str2;
int n;
cin>>n;
while(n--)
{
cin>>str2;
cin>>str1;
int pos=KMP(str1,str2);
cout<<pos<<endl;
}
return 0;
}