BF模式匹配算法
BF算法Brute-Force算法(蛮力算法),从主串的第pos个字符开始和模式串第1个字符比较,若相等继续比较后续字符,若不相等则回溯到主串第pos+1个字符开始重新比较
算法描述1.
#define max 20
typedef struct
{
char ch[max+1];//从1开始存储
int len;//字符串长度
}sstring;
int index(sstring *s,int pos,sstring *t)//从一存储
{
int i,j,k;
int m=s->len,n=t->len;
if(pos<1||pos>s->len)
return 0;
for(i=pos;i<=m;i++)
{
k=i;
for(j=1;j<=n;j++)
if(s[k]==t[j])
k++;
if(j==n) break;
}
return i-j;//返回位置
}
算法描述2.
#define max 20
typedef struct
{
char ch[max+1];//从1开始存储
int len;//字符串长度
}sstring;
int index(sstring *s,int pos,sstring *t)//从一存储
{
int i=pos,j=1;
if(pos<1||pos>s->len)
return 0;
while(i<=s->len&&j<=t->len)//判断条件 while循环一层循环
{
if(s->ch[i]==t->ch[j])//相同则继续比较
{
i++;j++
}
else
{
i=i-j+2;//主串回溯到i-j+2(即i的下一个字符)重新比较
j++;//模式串回到1
}
}
return i-t->len;//返回位置
}
KMP模式匹配算法
KMP算法的不同点在于消除BF算法中的主串s回溯的情况,只需要把模式串尽可能的向右滑动
若主串与模式串存在以下关系
S=S1S2...
S
i-j+1
S
i-j+2...
S
i-k+1...
S
i-1
S
i...
S
n
!= //Si!=Tj
Si!=Tj 时找到Tk-1=Tj-1,即Tk接下来与主串的Si比较
T= T1 T2T3 .... Tj-k+1....Tj-1Tj
!= //Tj!=Tk
T= T1....Tk-1Tk
next算法只与模式串有关与主串无关
令next[j]=k,即当模式串中第j个字符与主串相应字符“失配”时,在模式串中需重新与该主串相应字符比较的位置
next[j]=
0 当j=1时,即第一个字符就"失配",此时向右滑动一个位置即为模式串第一个字符
next[j]=max{ k |1<k<j且'
Tj-k+1....Tj-1Tj
'='
T1....Tk-1Tk
'} 此集合不为空时
next[j]=
1 其他情况 比如当j=2时,没有1<k<j的值,所以next[j]=1;
next[j]等于'T1....Tj-1'的真前缀字串与真后缀字串相等时的最大长度+1
next算法描述
void Get_next(sstring *t,int *next)
{
int j=1,k=0;
next[1]=0;
while(j<t->len)
{
if(k==0||t->ch[k]==t->ch[j])//k=0,k相当于前缀字符串的位置,j相当于后缀字符串的位置
{
k++; //当k=0或他们相等时(即相当于真前缀字串和真后缀字串相等),那么j++与主串相应字符不等时则让k++与之相比
j++;
next[j]=k;
}
else k=next[k]; //若当模式串第k个字符和第j个字符不等时,找到第k个字符的next值,继续与第j个字符比较
}
}
若在匹配过程中Si
=Tj
,则i++,j++,继续比较;否则j退回到next[j]继续与Si比较,若相等i++,j++,否则j继续退回到下一个next[j]的位置,这样会出现两种情况:一种是
j退回到某个next值(next[next[···next[j]]])继续与主串相应字符比较,另一种是j最终退回到0的位置(主串和模式串字符都向右滑动一个字符)
nextval函数
nextval函数在next函数上改进,例如主串为'aaabaaaab'模式串为'aaaab'时(next[1,2,3,4,5]={0,1,2,3,4}),
当主串的第4个字符b与模式串的第4个字符不等时还需要将b与a比较3次,而实际上只需要将模式串向右移4位据可以了,因此当主串字符i不等于模式串字符j并且模式串字符j等于模式串字符next[j]时,模式串字符i直接跳过与next[j]比较,直接与nextval[j](next[next[j...]]一直到不相等为止)比较
void Get_nextval(sstring *t,int *next,int *nextval)
{
int j=2,k;
nextval[1]=0;//当第一个不相等时像next一样,主串与模式串向右移一位
while(j<=t->len)
{
k=next[j];//记录j的next值
if(t->ch[k]==t->ch[j])//如果j位置与k位置的字符相等时,下一次比较主串和模式串直接跳过k,找到k的nextval值相比较
nextval[j]=nextval[k];
else nextval[j]=next[k]; //如果不相等则直接比较next的值
j++;
}
}
KMP算法描述
typedef struct
{
char *ch;//从1开始存储
int len;//字符串长度
}sstring;
int index(sstring *s,int pos,sstring *t)//从一存储
{
int i=pos,j=1,*next;
if(pos<1||pos>s->len)
return 0;
next=(int*)malloc((t->len+1)*sizeof(int)); //为next数组分配空间,存储每个模式串字符应该访问的位置
nextval=(int*)malloc((t->len+1)*sizeof(int));
Get_next(t,next);
Get_nextval(t,next,nextval);
while(i<=s->len&&j<=t->len)
{
if(j==0||s->ch[i]==t->ch[j])//j==0,j退回到0(即模式串与主串相应字符不等,模式串与主串下一个字符比较)
{ //字符相等继续比较
i++;j++;
}
else j=nextval[j];//模式串向右滑动,下一个模式串字符串与相应主串字符比较
}
if(j>t->len) return i-t->len;
else return 0;
}