给定一主串p,一子串q(称q为模式串) 若模式串与主串可找到匹配,则输出所有匹配下标
暴力算法为:i为主串字符下标,k为模式串下标,从0开始,与模式串一一匹配,
若不匹配,回溯i为i++,k回溯为0;则此算法时间复杂度为O(mxn)
KMP算法化简原理:每次模式串与主串不匹配需要回溯时,
k不需要回溯到第0个位置。
假设当前不匹配的模式串下标为t,则只需要回溯k=next[k]的位置之后继续比较,
若k为0时与主串还不匹配,则移动主串下标i,直到p[i]与q[0]相等,
此时则继续向后匹配,i++,k++;
问题的关键在于如何求模式串的next数组。
暂时偷懒不想更新如何求next数组
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
void get_next(char *s,int *next)
{
int len=strlen(s);
next[0]=-1;
int k=-1;
int j=0;
while(j<len-1)
{
if(k==-1||s[k]==s[j])
{
k++;
j++;
next[j]=k;
}
else
k=next[k];
}
}
void KMP(char *p,char *q,int *next,int *result,int &num)
{
int k=0;
for(int j=0;j<strlen(p);j++)
{
if(k==-1||p[j]==q[k])
{
if(k==strlen(q-1))
{
result[num++]=j;
k=0;
continue;
}
j++;
k++;
}
else
{
k=next[k];
}
}
}
int main()
{
char *p={"abddabcaabc"};
char *q={"abc"};
int num=0;
int *next=new int[strlen(q)];
int result[100]={0};
get_next(q,next);
KMP(p,q,next,result,num);
for(int i=0;i<num;i++)
cout<<i<<"-th: "<<result[i]<<endl;
system("pause");
}