本文共 4112 字,大约阅读时间需要 13 分钟。
代码如下:
#include#define OK 1#define ERROR 0#define MAXSTRLEN 255typedef int Status;typedef int ElemType;typedef unsigned char SString[MAXSTRLEN + 1]; //0号单元存放串的长度using namespace std;Status StrAssign(SString T,char chars[]){ //赋值 //生成一个其值等于chars的串T。 int i; if(strlen(chars)>MAXSTRLEN) return ERROR; T[0]=strlen(chars); for(i=0; i<=T[0]; i++) { T[i+1]=chars[i]; } return OK;}int BF(SString S,SString T,int pos){ int i = pos; int j = 1; if (pos<1) { cout<<"输入的位置不合理"< T[0]&&T[0]) cout<<"子串在主串中首字母的位置为"< < > a; StrAssign(S, a); cout<<"请输入要查询的子串:"; cin>>b; StrAssign(T, b); cout<<"请输入从子串的哪个位置之后开始查询:"; cin>>pos; BF(S,T,pos); return 0;}
KMP算法就是尽可能的把BF算法中的无意义的部分去掉。时间复杂度为 O ( m + n ) O(m+n) O(m+n).
KMP 算法的难点就在于去找到当主串在 S i S_i Si处失配后应该跟模式串的哪一个位置再开始匹配。这便是Next函数去解决的问题了。
Next函数的思路:
1.定义next[1] = 0.这个是为了方便函数的实现定的一个规定,之后你就知道奥妙了。 2.当模式串在 j j j 处跟主串失配后去看模式串已匹配区间[1, j-1]的最大相等前后缀的值,然后把这个值加1就是模式串在失配处的next值了。eg:
Next函数就是为了把模式串的每一个位置失配后要移动到的下一个位置保存在next数组里。
void Next(SString T,int next[]){ int j = 1; int k = 0; next[1] = 0; while(j
假设模式串为“abab”我们来根据代码跑一边。
1.最开始k = 0.所以!k肯定成立。执行if语句:j = 2,k = 1,next[2] = 1. 2.继续while循环,此时if条件不成立,k = next[1] = 0. 3.继续while循环,此时!k成立。执行if语句:j = 3,k = 1,next[3] = 1. 4.继续while循环,此时T[3] == T[1]成立。执行if语句:j = 4,k = 2,next[4] = 2.这个正好就是和咱们之前讲的next[ j ] 等于已匹配区间[ 1 , j-1 ]的最大相等前后缀的值加一。
到此如果还没看懂可以看下这个:
完整代码如下:
#include#define OK 1#define ERROR 0#define MAXSTRLEN 255typedef int Status;typedef int ElemType;typedef unsigned char SString[MAXSTRLEN + 1]; //0号单元存放串的长度using namespace std;Status StrAssign(SString T,char chars[]){ //赋值 //生成一个其值等于chars的串T。 int i; if(strlen(chars)>MAXSTRLEN) return ERROR; T[0]=strlen(chars); for(i=0; i<=T[0]; i++) { T[i+1]=chars[i]; } return OK;}int KMP(SString S,SString T,int pos,int next[]){ int i = pos; int j = 1; if (pos<1) { cout<<"输入的位置不合理"< T[0]) { cout<<"子串在主串中首字母的位置为:"< > a; StrAssign(S, a); cout<<"请输入要查询的子串:"; cin>>b; StrAssign(T, b); cout<<"请输入从子串的哪个位置之后开始查询:"; cin>>pos; int next[T[0]+1]; Next(T,next); KMP(S,T,pos,next); return 0;}
假如在某处字符a失配,根据next算好的跳转位置后还是字符a,那显然还是失配的。Nextval就是来把这些无意义的步骤给省去的。
eg:
这个实现起来也很简单,加一个if判断就ok了。代码如下:
#include#define OK 1#define ERROR 0#define MAXSTRLEN 255typedef int Status;typedef int ElemType;typedef unsigned char SString[MAXSTRLEN + 1]; //0号单元存放串的长度using namespace std;Status StrAssign(SString T,char chars[]){ //赋值 //生成一个其值等于chars的串T。 int i; if(strlen(chars)>MAXSTRLEN) return ERROR; T[0]=strlen(chars); for(i=0; i<=T[0]; i++) { T[i+1]=chars[i]; } return OK;}int KMP(SString S,SString T,int pos,int nextval[]){ int i = pos; int j = 1; if (pos<1) { cout<<"输入的位置不合理"< T[0]) { cout<<"子串在主串中首字母的位置为:"< > a; StrAssign(S, a); cout<<"请输入要查询的子串:"; cin>>b; StrAssign(T, b); cout<<"请输入从子串的哪个位置之后开始查询:"; cin>>pos; int nextval[T[0]+1]; Nextval(T,nextval); KMP(S,T,pos,nextval); return 0;}
转载地址:http://riil.baihongyu.com/