字符串查找算法BF和KMP

其中,Target为主串,Pattern为子串(模式串),如果在主串Target的第pos个位置后存在与子串Pattern相同的子串,返回它在主串Target中第pos个字符后第一次出现的位置,否则返回-1

1、 BF算法(Brute-Force,最基本的字符串匹配算法)
int BF(const string &Target,const string &Pattern,int pos)  
{  
    int i = pos;  //主串当前正待比较的位置,初始为pos  
    int j = 0;   //子串当前正待比较的位置,初始为0  
    int Tlen = Target.size();  //主串长度  
    int Plen = Pattern.size();  //子串长度  

    while(i < Tlen && j < Plen)  
    {  
        if(Target[i] == Pattern[j])   //如果当前字符相同,则继续向下比较  
        {     
            i++;  
            j++;  
        }  
        else   //如果当前字符不同,则i和j回退,重新进行匹配  
        {     
            i = i-j+1;  //Target退回下一轮开始比较的位置     
            j = 0;  //Pattern退回到子串开始处
        }  
    }  

    if(j >= Plen)  
        return i - Plen;  //返回匹配第一个位置
    else  
        return -1;  
}  
2、KMP

上述算法的时间复杂度之所以大,是由于索引指针的回溯引起的,针对以上不足,便有了KMP算法。KMP算法可以在O(Plen+Tlen)的时间数量级上完成串的模式匹配操作。其改进之处在于:每一趟比较重出现字符不等时,不需要回溯索引指针i,而是利用已经得到的部分匹配的结果将子串向右滑动尽可能远的距离,继续进行比较。它的时间复杂度为O(Plen+Tlen),空间复杂度为O(Plen)

KMP算法的关键是利用匹配失败后的信息(已经匹配的部分中的对称信息),尽量减少模式串(待搜索词)与文本串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,该函数本身包含了模式串的局部匹配信息。

void GetNext(const string &Pattern,int next[],int len)  
{  
    int j = 0;  
    int k = -1;  
    next[0] = -1;  

    while(j < len-1)  
    {  //p[k]表示前缀,p[j]表示后缀  
        if(k == -1 || Pattern[j] == Pattern[k])  
        {   //如果满足上面分析的Pk = Pj的情况,则继续比较下一个字符,  
            //并得next[j+1]=next[j]+1  
            j++;  
            k++;  
            next[j] = k;  
        }  
        else  
        {   //如果符合上面分析的第2种情况,则依据next[k]继续寻找下一个比较的位置  
            k = next[k];  
        }  
    }  
}  

int KMP(const string &Target,const string &Pattern,int pos,int next[])  
{  
    int i = pos;  //主串当前正待比较的位置,初始为pos  
    int j = 0;   //子串当前正待比较的位置,初始为0  
    int Tlen = Target.size();  //主串长度  
    int Plen = Pattern.size();  //子串长度  

    while(i < Tlen && j < Plen)  
    {  
        if(j==-1 || Target[i] == Pattern[j])     
        {       //如果当前字符相同,或者在子串的第一个字符处失配,则继续向下比较  
            i++;  
            j++;    
        }  
        else   //如果当前字符不同,则i保持不变,j变为下一个开始比较的位置  
        {     
            //next数组是KMP算法的关键,i不回退,  
            //而是继续与子串中的nex[j]位置的字符进行比较  
            j = next[j];  
        }  
    }  

    if(j >= Plen)  
        return i - Plen;  
    else  
        return -1;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值