高效的单字符串匹配算法Horspool

在单字符串匹配算法的领域中,有两种为人熟知的算法:KMP(看毛片)和BM算法,这两种算法虽然经典,不过难码。实际上许多简单的算法速度也是飞快。于是就让我们来认识一下BM的简化版——Horspool,效率比KMP、BM都快,还好理解。

原理


先来定义一些东西(S,原串;P,匹配串;‘|’匹配成功;‘#’匹配失败

Horspool看是否匹配时是从后往前扫描的,若全部匹配,则找到一个可匹配的方案free话,若有一个不匹配,则当前方案不存在free话真多。这时就要分情况讨论了。

情况一:

在下例情况中,称S中的‘d’为关键字符,就是P最后一个字符在S中的匹配字符。若P中除尾字符外没有与关键字符相同的字符,显然应该将P向后推len(P)个位置。

S - *****bcd*******
         #||
P -  2333acd
  -->       2333acd

情况二:

若P中除尾字符外有与关键字符相同的字符,显然应该将P向后推到P中最靠右的关键字符与S中的关键字符对齐。

S - *****bcd*******
         #||
P -  233dacd
  -->   233dacd

自我感觉比BM好多了,简洁高效。

代码


//实现查找S中有多少个与P完全相同的子串 
#include<cstdio>
#include<cstring>
using namespace std;
char S[1000],P[1000];
int ans,n,m;
int* HorspoolTable(const char *P){  
    int n = strlen(P);  
    int* ht=new int[256];  //ht:Horspool的表,255为ASCII上限 
    for (int i=0;i<256;i++)  ht[i]=n;//P中找不到这个字符就后移n位 
    for (int i=0;i<n-1/*不包括P中的尾字符*/;i++)  ht[(int)P[i]]=n-i-1;  
    return ht;  
}  
void Horspool(){  
    int* ht=HorspoolTable(P);  
    for(int i=0;i<=n-m;){  
        int k=n-1;
        for (k=m-1;k>=0&&S[i+k]==P[k];k--);  
        if (k==-1)  ans++; //全部匹配,ans++ 
        i=i+ht[(int)S[i+m-1]]; //否则后移对应位数 
    }  
    delete []ht;  
}  
int main(){
    scanf("%s%s",S,P);
    n=strlen(S);  
    m=strlen(P);  
    Horspool();
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41811117/article/details/80541174