字符串的模式匹配:Horsepool算法

Posted xlxxcc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串的模式匹配:Horsepool算法相关的知识,希望对你有一定的参考价值。

  Horsepool算法是Boyer-Moore算法的简化版本,这也是一个空间换时间的典型例子。算法把模式P和文本T的开头字符对齐,从模式的最后一个字符开始比较,如果尝试比较失败了,它把模式向后移。每次尝试过程中比较是从右到左的。

  Horspool 算法是一种基于后缀匹配的方法,是一种“跳跃式”匹配算法,具有sub-linear亚线性时间复杂度。

Horspool 算法思想:

  对于每个搜索窗口,该算法将窗口内的最后一个字符和模式串中的最后一个字符进行比较。如果相等,则需要进行一个校验过程。该校验过程在搜索窗口中从后向前对文本和模式串进行比较,直到完全相等或者在某个字符处不匹配。无论匹配与否,都将根据字符d在模式串中的下一个出现位置将窗口向右移动。

  移动的多少将根据窗口中最后一个字符在模式串中的位置进行移动。如果模式串中有多个相同的字符,选择最后一个字符为准(也就是字符在模式串从后往前上一次出现的位置,位置从左往右由0开始),以避免漏解。
  
  移动公式:
  移动距离 = 模式串长度 - 1 - 字符在模式串中从后往前上一次出现的位置。
  如果字符在模式串中没有出现,那么字符在模式串中从后往前上一次出现的位置为-1

  
  有模式串BARBER,它的每个字符移动距离如下:
  字符: A B E R
  距离: 4 2 1 3
  

Horspool 匹配过程:

假设有字符串T和模式串P如下:
字符串T: abddbccdabcd
模式串P: abc
模式串P长度3,字符串T长度12

1、字符串T和模式串P对齐

abddbccdabcd
abc

2、从后往前比较,比较T[2]和P[2],即字符”d”和”c”不匹配,而字符”d”不在模式串中,按照公式,移动位数 = 3 - 1 -(-1) = 3,移动后如下:

abddbccdabcd
   abc

3、从后往前比较,比较T[5]和P[2],即字符”c”和”c”匹配。
字符串T和模式串同时-1,比较T[4]和P[1],即字符”b”和”b”匹配。
字符串T和模式串同时-1,比较T[3]和P[0],即字符”d”和”a”匹配。
而字符”d”不在模式串中,按照公式,移动位数 = 3 - 1 -(-1) = 3,移动后如下

abddbccdabcd
      abc

4、从后往前比较,比较T[8]和P[2],即字符”a”和”c”不匹配。然而
而字符”a”出现在模式串位置0,按照公式,移动位数 = 3 - 1 - 0 = 2,移动后如下:

abddbccdabcd
        abc

5、从后往前比较,比较T[10]和P[2],即字符”c”和”c”匹配。
字符串T和模式串同时-1,比较T[9]和P[1],即字符”b”和”b”匹配。
字符串T和模式串同时-1,比较T[8]和P[0],即字符”a”和”a”匹配。
得到字符串匹配的位置: 8

Horspool 具体实现:

/**
  * 计算模式串每个字符移动的距离
  * 存放在dis数组
  */
int getDis(string &str,int *dis)
    int len = str.length();
    // 模式串中每个字符的移动距离,从左至右扫描模式,相同字符的最后一次改写恰好是该字符在模式串的最右边, 注意这里不包括最后一个
    for (int i = 0; i < len-1; i++)  
        dis[str[i]] = len-1-i;
    return 0;

匹配方法:

/**
 * 查找
 */
int Horsepool(string &text, string &pattern, int *dis)
    int j = 0;
    int pos = 0;
    int lenPattern = pattern.length();
    int lenTrext = text.length();

    while(pos <= lenTrext - lenPattern)
        j = lenPattern-1;
        // 搜索
        while(j>=0 && pattern[j]==text[pos+j])  
            j--;
        if(j==-1)
            return pos;
        else
            // 使用最后一个字符对齐的方法,进行“跳跃”移动
            pos += dis[text[pos+lenPattern-1]];
           
    
    // 匹配失败
    return -1;

以上是关于字符串的模式匹配:Horsepool算法的主要内容,如果未能解决你的问题,请参考以下文章

字符串模式匹配算法 Sunday算法

算法基础 - 朴素模式匹配算法、KMP模式匹配算法

【算法笔记】字符串匹配

kmp算法

字符串匹配基础上

字符串匹配算法的使用(未完待整理)