串的模式匹配算法

串的模式识别是指在主串中找到模式串的过程。

例如从主串abcdef寻找模式串ef,并返回模式串首字母在主串中的位置。

以ababcabc为主串abc为模式串为例。

ababcabc

   abc         (此时i=1,j=1回溯到i-j+2的位置)

基本算法如下:(接上篇文章中的String定义)

int Index(String S,String T,int pos)  //当两个字符相等时,将下标各往后增加1,如果不相等时,将j置1再次指向T的首字符,i进行回溯,用i减去当前j-1所指的长度再加上1代表

{                                                             //当前向后一个的位置,即i-j+2.

i=pos;

j=1;

while(i

{

if(S[i]==T[j])

{

i++;j++;

}

else

{

i=i-j+2;j=1;

}

}

if(j>T[0]) return i-T[0];

else return 0;

}

}

 

改进型KMP算法:

在上述的算法中有许多不需要进行的比较,例如:ababcabcabcababcaba为主串,ababcaba为模式串当比较至ababcabc不等于ababcaba时,若i指针进行回溯,则需比较babcabca是否等于ababcaba。由于我们已知在主串的c字符之前,二者是相等的。而模式串本身中由于babcabc并不等于ababcab(这个信息获取不涉及主串),所以模式串也不可能等于主串的下一个元素开始的串,即babca...因此我们在求解时不采用i指针回溯的方式,而是改变j指针的值。具体将j改为多少,请看下面的具体分析:串的模式匹配算法_第1张图片

 

因此上述方案的实现如下:

int Insert(String S,String T,int pos)

{

i=pos;j=1;

while(i

{

if(j==0 || S[i]==T[j])

{

i++;j++;

}

else

j=next[j];

}

if (j>T[0])

return i-T[0];

else return 0;

}

因此此时涉及到next[j]如何获取,这是一个递归的过程,假设next[j]=k,说明在j之前有k-1个元素是有相同串的,即:p1...pk-1=pj-k+1...pj-1,则此时next[j+1]=?

分为以下两种情况:

pj=pk,这种情况说明p1...pk=pj-k+1...pj,此时相同字符串的长度增加了1,有next[j+1]=next[j]+1。

pj<>pk,这种情况是一种模式匹配问题,此时模式串和主串相同,就是比较在这不同的串之前有没有最大长度的首尾相同串,例如例中,若模式abaabcac,若已知第6个字符c的next[6]=3,而p6<>p3,因此将此模式串向右滑动,p6<>p1,则next[7]=1.

这个的实现方法如下:

void next(String T,int next[])

{

i=1;next[1]=0;j=0;

while(i

{

if(j==0 || T[i]==T[j] )

{ i++;j++;next[i]=j;}

else j=next[j];

}

}

在下一篇中介绍关于next的修正算法,针对一些特殊的案例。

你可能感兴趣的:(串的模式匹配算法)