现在的位置: 首页 > 综合 > 正文

字符串匹配算法

2018年05月10日 ⁄ 综合 ⁄ 共 3970字 ⁄ 字号 评论关闭

 1、字符串匹配介绍       

        字符串匹配(String Matchiing)也称字符串搜索(String Searching)是字符串算法中重要的一种,是指从一个大字符串或文本中找到模式串出现的位置。

         如:文本串:P串 ASDFNMHUIOCIOHUIPNED

                模式串:  S串  HUIP

       S串在P串中对应位置如下所示

                P串 ASDFNMHUIOCIOHUIPNED

                S串                                         HUIP

 

2、字符串匹配算法

 (1)、回朔搜索法

算法思想:

    这是 一个最朴素的思路,将要模式串与文本字符串进行比较,有两种情况

      情况 1、若不匹配则模式串与下一个文本串进行比较

       如:P串 ASDFNMHUIOCIOHUIPNED

                S串  HUIP

        H和A不匹配则跳到下一个,将H与S进行比较,

    
如:P串     ASDFNMHUIOCIOHUIPNED

                S串       HUIP

        情况 2、若两个字符匹配,则将文本和模式串的指针都移动到下一个字符进行比较

            如P串 ASDFNMHUIOCIOHUIPNED

                    S串                   HUIP

                  P串的H与S串的H相匹配,所以将下一位P串中的U和S串中的U进行比较

          此时仍然会出现两种情况

    情况2.1、S串后面的字符与H串的一直相等,直到S串的末尾字符,则说明搜索成功,停止比较

           如:P串     ASDFNMHUIOCIOHUIPNED

                       S串                                            HUIP

          这是搜索成功的情况

  情况2.2、S串后面的某个字符与P串的不相等,说明此次匹配失败,将整个S串后移一位进行比较,同时S串指针移动到第一个字母,P串指针也移动到与S串对比的字符的位置,

          如:P串     ASDFNMHUIOCIOHUIPNED

                S串                             HUIP

          如上图,前面字符串HUI都是匹配的,到了第四个,P中的O与S中的P不再匹配了,说明此次匹配失败,S串后移

        如:P串     ASDFNMHUIOCIOHUIPNED

                S串                                HUIP

        P的指针从O移动到U,S中的指针从P移动到H;

    一直重复情况1、情况2步骤直到结束

算法评价:

     此算法虽然生动易懂,但算法复杂度太高。最坏的情况就是情况2.2中的最坏情况,每次都检索到最后一个才不匹配,此时算法复杂度为O(H.length*S.length)

     (2)KMP算法

    算法思想:

          KMP算法是对回朔搜索法中情况2.2的改进,相比蛮力算法,KMP 算法预先计算出了一个哈希表,用来指导在匹配过程中匹配失败后尝试下次匹配的起始位置,以此避免重复的读入和匹配过程。这个哈希表被叫做“部分匹配值表(Particial match table)”,它的设计是算法精妙之处。详情请看http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html,        

                在此说一下如何得到模式串部分匹配值next[i];

         如:S串:ABCDRTYABDABC

        1) 首先第0个字符(字符串从第0个算起)因为前面没有字符,不可能会有匹配情况,所以它的next值为0,

   即next[0]=0;

         2)定义俩个指针i,j分别指向S串字符即它的next值,因为第0个字符的next值已经知道,所以i初值为1,初始时i没有与任何字符进行匹配,故j初值为0;

        3)将S[i]与S[j]进行比较

       情况1:S[i]==S[j],说明第i个字符与前面的第j个字符匹配,匹配值加1;

     如:S串:ABCDRTYABDABC

        当匹配到红色A时,i=7,j=0,因为S[i]==S[j],所以到第i个字符的匹配值由0变成1;即j++,next[i]=j;即next[7]=1;     

      情况2S[i]!=S[j],j==0;说明从0到第i个字符一直没出现匹配值,j不做处理

      情况3:S[i]!=S[j],j>0;说明前面一部分字符是匹配的,但是此时不匹配,此时另next[i]=j显然不合适,但另

next[i]=0也是不可以的,因为到i的后缀可能会与j的一个前缀相等,故要将j进行相应更改,另j=next[j-1];循环情况3

       如  S串: ABDABCCDABDABHV

        此时j=5,指向C;i=13,指向H,所以j=next[4]=1,指向第一个B;重复执行情况3,因为此时仍然满足情况3的条件,所以j=next[0]=0,再次执行情况3,不满足条件,跳到情况2;

重复执行情况1到情况3直到结束

  

代码实现如图所示:

 
 
算法复杂度:
       由程序可得KMP的算法复杂度为O(s1.length+s2.length),因为while中循环次数不多;
(3)BM算法
    算法思想:  
         虽然BM算法复杂度达到O(m+n),但在实际中却很少使用,因为实际查找中出现abcabdab这种机率并不多
         在此说一下好后缀与坏字符规则:
      好后缀规则:
     情况1、存在另一个最长好后缀,此时不管它的位置在哪,都与好后缀匹配
             如 P串:HERE IS A SIMPLE EXAMPLE
                  S串:           ABPLEAPLE
            
此时最长后缀为PLE,因为S串前面存在PLE,故S串将前面的PLE与P串的PLE对齐即可
           如 P串:HERE IS A SIMPLE EXAMPLE

                  S串:                   ABPLEAPLE
    情况2、不存在最长好后缀,此时的相同好后缀必须在最前面才算,跟KMP算法中的匹配串一样
            如:P串:HTTP HE RE ISCABCD EFBHI
                   S串:                BABDCAB
              
因为不存在最长好后缀CAB,所以尽管存在较长的后缀AB,但因为AB不在初始位置,所以不可选,而是选择后缀B
            如:P串:HTTP HE RE ISCABCD EFBHI

                   S串:                              BABDCAB

   

   坏字符规则:P串指针指向的字符与S串指针指向的字符不相等
     情况1、P串的字符与S串前面所有字符都不相等,S串第一个直接跳到与P串下一位比较
     如:P串:HERE  I S A SIMPLE EXAMPLE
            S串:EXAMPLE
          
S与E不相等,且S与E前面所以字符不相等,所以S串可以直接跳到下一位
           如:P串:HERE   I S  A  S IMPLE EXAMPLE

                  S串:                 EXAMPLE
    情况2、P串的字符与S串某个字符相等,则将最近的一个与P中的字符对齐
          如:P串:HERE   I S  A  S IMPLE EXAMPLE

                 S串:                 EXAMPLE
        P与E不相等,但P与E前面的P相等,所以将其对齐
           如:P串:HERE   I S  A  S IMPLE EXAMPLE

                  S串:                     EXAMPLE
      得坏字符规则中移动位数为:与P对比的字符在S中的位置减去最近的一个与P对比的字符相等的位置 
      如情况1:   6-(-1)=7    P串中的S与 S串的每个字符都不相等,所以S在S串的位置为-1
          情况2:6-4=2
  算法复杂度:
       1、该算法之所以会比KMP算法优,原因在于从后面开始比较,当后面条件不满足时,前面也无需比较了
      如:P串:HERE   IS A SIMPLE EXAMPLE

            S串: EXAMPLE
       上面情况只需比较一次,S串就可以前进7位,而KMP算法则需要前进7步,这对于重复性小的字符串的查找很有优势
    2、每次移动位数取好后缀与坏字符的最大值,充分考虑了各种情况

抱歉!评论已关闭.