KMP算法是模式匹配的一种改进算法,是D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的。
一般情况下,当主串i字符与匹配串j字符不等时,j会退回到0,i退回到原来位置的下一位,这样效率低。
KMP算法的实现思路
从主串的第一个字符(或者给定的第pos个字符)开始和子串的第一个字符开始比较,若相等,则继续比较后面的字符。若不相等,则将模式串右移至合适的位置,找出模式串中合适的第k位与主串中发生不等的位进行对齐比较。算法继续。
模式串与主串对齐继续比较的第k位必须满足其前k-1位与主串发生失配位置的前k-1位匹配,且该k-1位字串必须是最长的字串(即不存在k’>k,使模式串中的前k’-1位与主串发生失配位置的前k’-1位匹配,这是为了保证不漏过可以匹配的串)。
该算法中的主程序同普通的匹配算法类似,区别在于当发生不匹配时,主串指针不需要回退(不动),将模式串右移到合适的位置继续进行比较。当匹配串位置j==-1时,主串指针右移一位,匹配串右移一位。该算法的关键是模式串next[]的取得。
next[]的取得
next[]的取得同样是KMP,只是这时候主串和匹配串是同一个串
next[0] = -1;next[1] = 0;
i = 0;j = 1;
if(s[i] == s[j]) {i++;j++;next[j] = i;}
else j = next[j];//不等时,j退回到一个何时的位置
源码(来自数据结构(c语言版)严蔚敏 吴伟民,略有改动)
#include <iostream.h>
#include <cstdlib>
#include <cstring>
using namespace std;
#define MAX 50
int next[MAX];
void get_next(string t)
{
int len = t.size();
int i = 0,j = -1;
next[0] = -1;
while(i < len)
{
if(j == -1 || t[i] == t[j])
{
++i;++j;
next[i] = j;
}
else
j = next[j];//j回退到合适的位置
}
}
int KMP(string s,string t,int pos)
{
int s_len = s.size();
int t_len = t.size();
int i = pos - 1,j = -1;
while(i < s_len && j < t_len)
{
if(j == -1 || s[i] == t[j])
{
++i;
++j;
}
else j = next[j];
}
if(j == t_len)
return i - t_len;
else return 0;
}
int main()
{
string s,t;
cin>>s>>t;
get_next(t);
cout<<KMP(s,t,0)<<endl;
system("pause");
}