KMP算法与改进next数组比较次数的输出
一、教材与实际实现的差距
我使用的是这样的一个字符存储结构
#define MAXLEN 255
typedef struct
{
char ch[MAXLEN+1];//加一是为了存储结束标记
int length;//一般用length来判断字符结束
}SString;
那么,在给字符串结构体赋值的时候就无法使用以下形式,而是要用
#include <iostream>
using namespace std;
int main()
{
SString T;
//T.ch="aaabaaaab";这句话有错误
cin>>T.ch;
}
如果使用cin来给T这个字符串赋值那么就会出现字符从ch[0]开始存储
而教材给出的计算next函数和KMP算法的函数中都是从ch[1]开始考虑的
void get_next(SString T,int next[])
{
i=1;next[1]=0;j=0;//变量自行定义
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
++i;++j;next[i]=j;
}
else j=nextp[j];
}
}
二、提出两种解决方法
第一种
可以保持原来ch[1]开始比较的方法,通过改变初始化的条件达到目的,KMP则可以保持不变,但是需要使用字符指针和strcpy函数,实现相对复杂,不推荐。
void get_next(SString T,int next[])
{
i=1;j=0;
next[0]=next[1]=0;//教材只定义了next[1]为0
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
++i;++j;next[i]=j;
}
else j=nextp[j];
}
}//该方法会多出一个0在next[0]处
第二种
将next[0],起始判断数改为-1,这样既不影响循环向下进行next数组的赋值,也不用改变T.ch,就可以愉快的套函数啦~~ 2333
void get_next(SString T, int next[])//计算next的值
{
i = 0; next[0] = -1; j = -1;
while (i<T.length)
{
if (j == -1 || T.ch[i] == T.ch[j]){ ++i; ++j; next[i] = j; }
else j = next[j];
}
}
KMP函数也需要改一些起始变量
int Index_KMP(SString S, SString T, int pos) //KMP算法
{
i = pos - 1; j = 0;//关键在起始变量的赋值
while (i<S.length&&j<T.length)//在这之前需调用一次获取next数组的函数
{
if (j == -1 || S.ch[i] == T.ch[j]){ ++i; ++j;}
else{ j = next[j];};
}
if (j >= T.length) { return i - T.length + 1; }
else return -1;
}
三、统计KMP子串和主串对比的次数
改进的next数组相同
第一种
这种算法可以比较整个主串中多个子串比较次及出现的位置,改变循环条件其实也可以只返回第一次出现子串的位置和比较次数
int Index_KMP(SString S, SString T, int pos)
{
while (i < S.length){
while (j != -1 && S.ch[i] != T.ch[j])
{
j = next[j]; m++;
}
if (i != 0 && S.ch[i] == T.ch[j])m++;
if (i == j&&i==0)m++;
i++; j++;
if (j >= T.length){
time[temp] = m;
k[temp] = j;//m++;
temp++;
j = next[j];
}
}
cout << "KMP算法比较次数" << m << "次" << endl;
cout << "子串在主串中出现过" << temp << "次" << endl;
for (int i = 0; i < temp; i++)
{
cout << "第" <<i+1<<"个的比较次数为"<<time[i]<< endl;
cout << "出现的位置在" << k[i] << endl;
}
}
第二种
这一种只需要在两个判断条件中统计次数就行
int Index_KMP(SString S, SString T, int pos)
{
i = pos - 1; j = 0;
while (i<S.length&&j<T.length)
{
if (j == -1 || S.ch[i] == T.ch[j]){ ++i; ++j; m++; }
else{ j = next[j]; if(j!=-1)m++; };
}
cout << "KMP算法中一共比较" << m << "次" << endl;
if (j >= T.length) { return i - T.length + 1; }
else return -1;
}
只是个人代码总结与思考,如有错误请及时告诉我并予以更正。
参考教材:《数据结构(c语言版)》(第二版)严蔚敏