本例中我们使用的是一般的string 而不是T[0] = length
/////////////////////////////////////////////////////////////源文件****************************************************
#include <iostream>
using namespace std;
#define INI_SIZE 100
//=======================
typedef struct
{
char * base;//the base pointer
int length;//the string length
}MString;//this string is exist in the heap
int InitString(MString &store,char * input)
{//put the char into the MString;
store.base = (char *)malloc(INI_SIZE*sizeof(char));
store.length = 0;
int i =0;
int j = 0;
while(input[i]!=0)
{
store.base[j++] = input[i++];
++store.length;
}
return 0;
}
void show(MString &store)
{
for(int i =0;i<store.length;++i)
{
cout<<store.base[i];
}
cout<<endl;
}
int StrCat(MString &str1,MString &str2)//connect the str2 behind the str1
{
if((str1.length+str2.length)>INI_SIZE)
str1.base = (char *)realloc(str1.base,(str1.length+str2.length)*sizeof(char));
int len1 = str1.length;//*/*注意这里的变量 变量是在变化的 不能用变换的东西去干扰const
for(int k =0;k<str2.length;++k)
{
str1.base[len1+k] = str2.base[k];
str1.length++;
}
return 0;
}
int StrCmp(MString &str1,MString &str2)
{//if the str2 is equal to str1 then return 0 else return the str1.length - str2.length
int i;
int j;
i=str1.length;
j = str2.length;
while(--i&&--j)
{
if(str1.base[i]!=str2.base[j])
return str1.length - str2.length;
}
if(i||j)
return str1.length - str2.length;
else
return 0;
}
int StrSub(MString main,MString &sub,int pos,int length)
{
//get the substring from the main string from the pos and the length is the sub's
sub.base = (char *)malloc(INI_SIZE*sizeof(char));
sub.length = 0;
for(int i = 0;i<length;++i)//i is just used for count
{
sub.base[i]=main.base[pos++];
++sub.length;
}
return 0;
}
int StrGetLength(MString str)
{
return str.length;
}
void ClearList(MString &main)
{
main.length = 0;
free(main.base);
}
int MoveMatch(MString main_static,MString sub_dynamic)//if return the int it is the first destination index(from 0 to n) of the main string
{
int i,j;
i = j = 0;
while(i<main_static.length && j<sub_dynamic.length)
{
if(main_static.base[i] == sub_dynamic.base[j])
{
++i;
++j;
}
else
{
i = i-j+1;
j = 0;
}
}
if(j == sub_dynamic.length)//in this case the substring is matched
return (i-sub_dynamic.length);
else
return -1;//sub_dynamic can not be matched in the main string k
}
int StrKMPAlog(MString main,MString son)
{
int i,j,k;
i=j=0;k = 1;
while(i<main.length && j<son.length)
{
if(main.base[i] == son.base[j])
{
i++;
j++;
k++;//this parameter is used for accout the number of the equal element
}
else
{
i=i+k;
j = 0;
}
}
if(j == son.length)//in this case the substring is matched
return (i-son.length);
else
return -1;//sub_dynamic can not be matched in the main string k
}
int FindNext(MString main,int *next)
{
int i;//used for go around the next array
int j;//be the pointer to point to the son String
//main.base[]
i = 0;
j = -1;
next[0] = -1;
while(i<main.length)
{
if(j == -1||main.base[i] == main.base[j])
{
++i;
++j;
next[i]=j;// when it is equal next[j+1] = k+1;next[j+1] = next[j]+1 as j is added by itself so we can do it like this
}
else//reback to the next simililar point and compare
j=next[j];//change the j by using the next arrary
}
return 0;
}
int Kmp(MString main,MString son,int next[])
{
int mainI =0;
int sonI = 0;
while(mainI <main.length && sonI<son.length)
{
if(sonI==0||main.base[mainI] == son.base[sonI])
{
++mainI;
++sonI;
}
else
sonI = next[sonI];
}
if(sonI == son.length)
return mainI-son.length+1;
else
return 0;
}
//*************************************************************************END OF THE SOURCE===============================================
//====================================================STATR OF THE TEST FUNCTION =======================================
int main()
{
MString test1,TEST2,test3;
cout<<"plsez insert some chars"<<endl;
char* h1="abababaabaa abaabc bcdcabcd";
char* h2="abaabc";
InitString(test1,h1);
InitString(TEST2,h2);
cout<<test1.length<<endl;
cout<<TEST2.length<<endl;
cout<<"*-*-*-*-*-**-*-*-*-**---*"<<endl;
//=================strKMP TEST*****************************************************************************************
//int * next = (int*)malloc(sizeof(int)*TEST2.length);
int * next = new int[TEST2.length];
FindNext(TEST2,next);
for(int i = 0;i<TEST2.length;++i)
cout<<next[i]<<endl;
cout<<"KMP"<<
Kmp(test1,TEST2,next)<<endl;
system("pause");
return 0;
}
kmp 算法的关键是咋next函数的求取 从本质上来说next函数是一个定义域为整数的离散函数
它的目的是求取任意一个字符的回溯位置 next函数有两个重要性质;这两个重要性质是
1、当比较到pj==pi时那么next[j+1] = next[j]+1 就是说next[j+1] = k+1 也就是说在如果两个比
较是相等的话那么后面一个字符的next函数值肯定是前面的加1
2、当比较pj!=pi的时候这个时候 做为模式串就要回溯了,回溯到哪里?回溯到next[j]的位置就是
程序中所写的 j=next[j] j指针的位置发生了变化。
ps:next函数本来就是一种迭代关系的函数 对于这种函数要找到它的规律,从简单的人力劳动中总
结出来一般的原理,当然对于手工的计算也要多做几次,然后让手工的技巧不断模式话,这样的话离
最终写出计算机源代码也不远了、