问题:
在一个长度为m的字符串source中,寻找 长度为n的字符串target。如果source字符串中存在target字符串,则返回字符串target第一次在字符串source出现的位置,若不存在,则返回-1。
这里涉及到一个算法–KMP算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)。
同时,这里也需要了解什么是真前缀和真后缀
举一个例子:
字符串:china
真前缀:c,ch,chi,chin.
真后缀:hina,ina,na,a.
现在就到了上代码的时候
先是暴力算法:(给出重要部分部分)
int Index_1(char s[],int sLen,char p[],int pLen){//s为主串,sLen为主串元素个数,p为模式串,pLen为模式串的个数
if(sLen<pLen)return 0;
int i = 1,j = 1;
while(i<=sLen && j<=pLen){
if(s[i]p[j]){i++;j++;}
else{
i = i-j+2;
j = 1;
}
}
if(j>pLen) return i-pLen;
return 0;
}
接下来就是KMP算法:(有关构建nest数组的部分,有两种)
1.int ne(char a[],int len,int next[])//a是模式串,len是模式串的长度
{
next[1]=0;
int i=1,j=0;
while(i<len){
if(j0||a[i]==a[j])
next[++i]=++j;
else
j=next[j];
}
}
2.for(int i=2,j=0;i<=n;i++)//p是模式串
{
while(j&&p[i]!=p[j+1])
j=next[j];
if(p[i]==p[j+1])
j++;
next[i]=j;
}
最后给出一完整的代码:(比较特殊)
#include
using namespace std;
const int N=10010,M=100010;
int n,m;
int ne[N];
char s[M],p[N];
int main()
{
cin>>n>>p+1>>m>>s+1;
for(int i=2,j=0;i<=n;i++)
{
while(j&&p[i]!=p[j+1])
j=next[j];
if(p[i]==p[j+1])
j++;
next[i]=j;
}
for(int i=1,j=0;i<=m;i++)
{
while(j&&s[i]!=p[j+1])
j=ne[j];
if(s[i]p[j+1])
j++;
if(jn)
{
cout<<i-n;
j=ne[j];
}
}
return 0;
}