KMP算法是使用了next数组,改良后的在next数组基础上进行2次模式参照,某一个字符与模式串不匹配则沿用其前一位字符的next值
由于清华版的《数据结构(c语言版)》的类C代码使用的是下标从0开始,0作为长度存储位,与实际的C/C++标准库不一样,所以讲其改为纯C/C++标准实现,使用std库的string类,由此引发了数组下标的问题。在使用string库的迭代器进行定位字符的话,可以将0对应为begin(),-1对应为begin()-1,(即越下界)。
当nextVal为-1时,则主串应该向右滑动,同时模式串置为初始状态index=0。
原KMP算法原理:
next[j] =
{
-1,当j=0时,即模式串回至起始下标
Max{k|0
0,其他情况,无有效模式参照信息
}
改良的KMP则在Max集合保存有效比较信息,公式1:假如P(k) = P(j),则nextVal[j+1] =next[j]+1;若不等,则模式串应该向右滑动(即自身下标减小),直至满足公式1,实在寻找不到合适的则
下面的代码是残缺的,因为新浪的文字编辑器过滤算法有问题总是发现无法处理程序字符,详细无错代码可以到我的其他博客上
// KMP.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
using namespace std;
void getNextVal(const string t,int * nextVal)
{
int i = 0;
nextVal[0] = -1;
int j = -1;
int size = static_cast(t.length());
//这是重点1
while (i
{
if (j==-1 || t.c_str()[i]==t.c_str()[j])
{
++i;++j;
if (t.c_str()[i]!=t.c_str()[j])
{
nextVal[i] = j;
}
else
{
nextVal[i] = nextVal[j];
}
}
else
{
j = nextVal[j];
}
}
}//getNextVal
bool Index_KMP(const string &s,const string &t,int&targetIndex,int beginPos = 0)
{
cout<<"okkkkkkkkk";
int * nextVal = new int[t.length()+1];
int i = beginPos;int j = -1;
getNextVal(t,nextVal);
//signed和unsigned转化问题,要认真处理
int s_size = static_cast(s.length());
int t_size = static_cast(t.length());
while (i<<span style="line-height: 21px;">s_size&& j<</span>t_size)
{
if (j == -1 || s.c_str()[i]==t.c_str()[j])
{
++i;
++j;
}
else
{
j = nextVal[j];
}
}
delete[] nextVal;
if (j>=t_size)
{
targetIndex = i - t.length();
cout<<"\n"<<i<<"\t"<<j<<"\t"<<targetIndex;
return true;
}
else
{
return false;
}
}//Index_KMP
int _tmain(int argc, _TCHAR* argv[])
{
string s = string("acabaabaabcacaabc");
string t("abaabcac");
int index = 0;
Index_KMP(s,t,index);
cin>>index;
return 0;
}