5.1 朴素的模式匹配算法(BF算法(Brute Force))
5.1.1原理分析
5.1.2 代码实现
#include <stdio.h>
int BF(char S[],char T[]);
int main(void)
{
//主串
char S[] = "abcabcacb";
//模式串
char T[] = "abcac";
//匹配查找
printf("BF:%d\n",BF(S,T));
}
int BF(char S[],char T[])
{
int i=0,j=0;
//当S没有结束并且T也没有结束
while(S[i] != '\0' && T[j] != '\0')
{
if(S[i]==T[j])
{
i++;
j++;
}
else //i和j分别回溯
{
i = i-j+1;
j=0;
}
}
if(T[j]=='\0') //匹配成功,返回本次匹配的开始位置(不是下标)
{
return i-j+1;
}else{
return 0;
}
}
5.2 KMP算法
5.2.1 原理分析
基本思想:主串不回溯
版本一:j从0开始,next从-1开始 (我比较喜欢j从0开始)
列如:主串S=“ababaababcb”, 模式T=“ababc”,则该模式的next值计算如下:
j=0时,next[0]=-1;
j=1时,此时j由0到j-1的串只有“a”,属于其他情况next[1]=0;
j=2时, 此时j由0到j-1的串有“ab”,T[0]!=T[1],则next[2]=0;
j=3时, 此时j由0到j-1的串有“aba”,T[0]=T[2],则next[3]=1;
j=4时, 此时j由0到j-1的串有“abab”,T[0] T[1]=T[2] T[3],则next[4]=2;
版本二:J从1开始,next从0开始:
2.5.2 KMP算法的实现
#include <stdio.h>
void GetNext(char T[],int *next);
int KMP1(char S[],char T[]);
int length(char L[]);
int main(void)
{
//主串
char S[] = "ababaababcb";
//模式串
char T[] = "ababc";
//匹配查找
printf("KMP1:%d\n",KMP1(S,T));
return 0;
}
/*求字符串长度*/
int length(char L[])
{
int i=0;
while(L[i] != '\0')
{
i++;
}
return i;
}
//*next数组*/
void GetNext(char T[],int *next)
{
int j=0,k=-1;
next[0]=-1;
while(j < length(T))
{
if(k==-1 || T[j] == T[k])
{
++j;
++k;
next[j]=k;
}else{
k=next[k];
}
}
}
{
int i=0,j=0;
int next[5];
GetNext(T,next);
/*当S没有结束并且T也没有结束*/
while(i < length(S) && j < length(T))
{
if(j==-1 || S[i]==T[j])
{
++i;
++j;
}
else /*j回溯*/
{
j=next[j];
}
}
if(j >= length(T)) /*匹配成功,返回本次匹配的开始位置(不是下标)*/
{
printf("i=%d,j=%d,T[j]=%c \n",i,j,T[j]);
return i-j+1;
}else{
return 0;
}
}
改进kmp算法:
注:此处讲解j是从1开始的,只是演示思路,程序设计还是以j=0开始
有以上的思路理解,对kmp算法改进如下:
j | 0 | 1 | 2 | 3 | 4 |
T | a | b | a | b | c |
next[j] | -1 | 0 | 0 | 1 | 2 |
nextval[j] | -1 | 0 | -1 | 0 | 2 |
#include <stdio.h>
void GetNextVal(char T[],int next[]);
int KMP2(char S[],char T[]);
int length(char L[]);
int main(void)
{
//主串
char *S = "ababaababcb";
//模式串
char *T = "ababc";
//匹配查找
printf("KMP2:%d\n",KMP2(S,T));
return 0;
}
/*求字符串长度*/
int length(char L[])
{
int i=0;
while(L[i] != '\0')
{
i++;
}
return i;
}
/*改进kmp算法的next数组*/
void GetNextVal(char T[],int next[])
{
int j=0,k=-1;
next[0]=-1;
while(j<length(T))
{
if(k==-1 || T[j] == T[k])
{
++j;
++k;
if(T[j] != T[k])
{
next[j]=k;
}else{
next[j]=next[k];
}
}else{
k=next[k];
}
}
}
{
int i=0,j=0;
int next[5];
GetNextVal(T,next);
/*当S没有结束并且T也没有结束*/
while(i<length(S) && j<length(T))
{
if(j==-1 || S[i]==T[j])
{
++i;
++j;
}
else /*j回溯*/
{
j=next[j];
}
}
if(j>=length(T)) /*匹配成功,返回本次匹配的开始位置(不是下标)*/
{
return i-j+1;
}else{
return 0;
}
}