数据结构之字符串的模式匹配

来源:互联网 发布:桌游淘宝 编辑:程序博客网 时间:2024/06/06 03:23

字符串的模式匹配问题:

一共有两种算法,

1.朴素模式匹配算法。

举例而言(寻找从S=”goodgoogle”中找到V=”google”这个子串):我们一般需要以下的步骤

(1).从主串的第一个字符开始,SV中的字符逐一比较,可以发现前三个匹配成功而第四个没有匹配成功(竖线代表成功,折现代表失败)。

         

(2)主串的开始下表+1,又继续与子串进行匹配

        

(3)如果没有匹配成功那么继续重复第二步,直到全部匹配成功,或者直到s到达末尾匹配失败。

        

实现代码:

//返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0.//T非空,1<= pos <=s.lengthPublic int ndex(String s,String v,int pos){   int i = pos-1;    //  i用于主串s中当前位置下标,若pos不为0,则从post的位置开始   int j = 0;     //  j用于子串v的当前位置下标。   while(i<s.length  &&  j<v.length){    //若i小于s的长度,且j小于v的长度时循环       if(s[i] == v[j]){          //如果当前主串对应字符和子串对应字符相等          i++;          J++       }else{          //说明在匹配某个过程中,当前s的对应字符与v对应字符不相等。          i = i - j + 1; //退回到上次匹配开始的下一个字符          j = 0;  //将J退回到子串的开头       }   }  if (j > v.length-1){     return  i - v.length + 1;  }else {     return 0;  }}

对于上面的算法,我提出一些改进意见就是,匹配的终止条件可以具体一些,减少循环的次数。当主串的剩余子串长度小于要寻找的子串长度时,就可以停止匹配了。

可以在while中比较两个字符串相等位置的代码之前,加一个大的判断if(s.length-1 - i < v.length ),如果满足条件直接break,跳出循环,后面的字符可以不用比较。

 

 

2.KMP模式匹配算法(是对1算法的改进)

  假如有主串 S= “abcdefgab”;  匹配子串:T=”abcdex”;我们使用上面的朴素匹配法过程如下。

 

如果我们认真观察其实可以发现②③④⑤步骤是不需要的,是重复的无用操作。因为我们可以发现对于子串的首字符a并不与后面任意一个字符相等,并且如果出现①中的这种现象,子串的前5个字符与主串相等,那么就意味着子串T不可能在于主串S中的2-5号字符相等,2-5号操作是多余的。这就是KMP算法改进朴素算法的地方。

 

KMP模式匹配算法的核心是:如果我们知道子串T的首字符与T中后面的字符均不相等(这是前提),如果在出现如①的情况,即子串的前部分与主串的前部分字符相等,但是从i号不相等,那么我们可以断定以到 i-1号任意一个字符开头的字符串不可能与子串匹配成功,那么主串的到 i-1号不需要进行判断,直接从i号开始判断。

 

 

 

如果子串中有与首字符重复的子符,该怎么办?我们以S=”abcabcabc” T=”abcabx”为例说明。首先继续朴素匹配算法。

 

因为首字符a有重复,我们不能继续运用上面的规则,但是我们可以发现,到第二个出现首字符之前的字符我们是可以使用规则,将其规避掉,即②与③去掉,不要判断。

因此:对于子串中有与首字符相等的字符,可以省略掉一部分不需要的判断。

这里如何判断与首字符相同的不同位置字符,对算法的影响,参考《大话数据结构》P139.

0 0
原创粉丝点击