改进的KMP算法

 

//C.h 几乎各程序都需要用到的文件包含宏命令和使用名空间
#ifndef _C_H_
#define _C_H_
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <cstdarg>
#include <assert.h>
using namespace std;
#endif
#include "C.h"
class HString
{
private:
char *ch;
int length;

public:
HString()
{
ch=NULL;
length=0;
}

HString(const char *str)
{
length=strlen(str);

ch=new char[length];

assert(ch!=NULL);

for (int i=0;i<length;i++)
{
ch[i]=str[i];
}

}

HString(const HString &S)
{
length=S.length;
ch=new char[length];
for (int i=0;i<length;i++)
{
ch[i]=S.ch[i];
}
}

~HString()
{//析构函数;
ClearString();
}

void ClearString()
{//清空字符串;
if (ch!=NULL)
{
delete [] ch;
ch=NULL;
}

length=0;
}

void StrAssign(const char *str)
{//产生与源字符串相同的串;
ClearString();//释放原有空间;

length=strlen(str);

if (length)
{
ch=new char [length];

assert(ch!=NULL);

for (int i=0;i<length;i++)
{
ch[i]=str[i];
}
}
}

// bool StrEmpty() const//判断字符串是否为空;
// {//如果为空则返回True,否则返回False;
// return length==0;
// }
int compare(const HString &S) const
{
for (int i=0;i<length&&i<S.length;++i)
if (ch[i]!=S.ch[i])
return ch[i]-S.ch[i];

return length-S.length;
}

int StrLength() const
{//返回串长;
return length;
}

bool substring(HString &sub,int pos,int len) const
{
if (pos<1||pos>length||len<0||len>length-pos+1)
{
return false; 
sub.ClearString();
}

 

if (len)//字串非空;
{
sub.ch=new char[len];

assert(sub.ch!=NULL);

for (int i=0;i<len;i++)
{
sub.ch[i]=ch[pos-1+i];
}
sub.length=len;
}
return true;
}

 


};

void getnext (HString S,int next[])
{//求next数组的值

int i=1,j=0;
HString sub1,sub2;
next[1]=0;//s的第一个字符与主模式串失配时,主串的下一个字符与s的第一个字符比较;
while (i<S.StrLength())
{
S.substring(sub1,i,1);//s的第i个字符在sub1中;
S.substring(sub2,j,1);//s的第j个字符在sub2中;
if (j==0||sub1.compare(sub2)==0)
{
++i;
++j;
S.substring(sub1,i,1);
S.substring(sub2,j,1);
if (sub1.compare(sub2)!=0)
next[i]=j;
else
next[i]=next[j];
}
else
j=next[j];
}
}

int Index_KMP(HString T,HString S,int pos,int next[])//匹配过程;
{
int i=pos,j=1;

HString sub1,sub2;

while (i<=T.StrLength()&&j<=S.StrLength())
{
T.substring(sub1,i,1);
S.substring(sub2,j,1);

if (j==0||sub1.compare(sub2)==0)
{
++i;
++j;
}
else
j=next[j];
}
if (j>S.StrLength())
{
return i-S.StrLength();
}

else
return 0;

}

void main()
{
int i,*p;
HString s1("abcdabcdefg"),s2("abcde");

p=new int[s2.StrLength()+1];

getnext(s2,p); //求得s2的next数组,存在p数组中;

for ( i=1;i<=s2.StrLength();i++)
{
cout<<*(p+i);
}
cout<<endl;

i=Index_KMP(s1,s2,1,p);

if (i)
{
cout<<"子串与主串在"<<i<<"处配对"<<endl;
}
else
cout<<"子串与主串匹配不成功!"<<endl;
}


个人觉得改进的KMP算法中最重要的就是求next数组,只要掌握了next数组的求法,该算法的精髓就被掌握了

posted @ 2012-04-09 22:25  zh yu  阅读(529)  评论(0编辑  收藏  举报