BF算法、KMP算法及思想

BF算法

当我们在进行字符串匹配时,我们会把主串和模式串,从某个位置,我们记为【pos】,开始匹配,每匹配成功一个字符,就让i加一。可一旦“失配”,我们就会让i回溯,从pos的下一个字符开始,重新执行上面的过程,直到模式串被匹配完。

int Index_BF(string str1, string str2, int pos = 1)
{
    int i = pos, j = 1;
    while(i < str1.length() && j < str2.length())
    {
        if(str1[i] == str2[j]) {i++;j++;}
        else {pos++;i=pos;j=1;}
    }
    if(j == str2.length())
        return i - j + 1;
    else
        return 0;
}

KMP算法

KMP算法的精髓所在,就是当“失配”时,不需要将i重新回溯到pos的下一个。 而是将模式串向右滑行,尽可能远的距离。因为在模式串中,当“失配”时,如果当前“失配”字符的前k个字符,和模式串的最开始的k个字符,如果相等,那么这k个字符,是不需要再进行比较的,直接让主串的第i个字符,和模式串的第k+1个字符开始比较就可以了。
比如当我们比较
在这里插入图片描述
i从8到15,在15时“失配”。本来按照BF算法,i是要从9重新开始的。但我们仔细观察,可以发现在模式串中,相对于这个失配字符,前三个字符与后三个字符是相等的
在这里插入图片描述所以我们可以让i不动,仍然为15,但让模式串的j等于“相等字符数加一”也就是4,让主串的第十五个字符,和模式串的第四个字符进行匹配。这样前面的三个字符就不需要再匹配了。
在这里插入图片描述那么相对于模式串中的f,它的k值,就为3+1;全部字符的k值,我们存在一个叫做next的数组中,它记录了当这个字符失配时,我么跳到哪一个字符。技巧:它的值为当前字符的,前面的,字符串的,首尾重合数加一。 不过这个技巧只能用来应付考试,计算某个模式串的next数组。这个求next数组的方法,代码实现好像有点困难。

next数组的计算方法

//比较第i个字符,与第j个字符是否相等
//如果相等,那么就让下一个字符的next值等于j+1
//如果不相等,就好比失配,就让j往前等于next[j]
//重复第一步,直到j等于零
//j等于零,说明第一个字符都与第i个字符不相等

代码实现

#include<iostream>
using namespace std;
void Get_Next(string str,int next[])
{
    //比较第i个字符,与第j个字符是否相等
    //如果相等,那么就让下一个字符的next值等于j+1
    //如果不相等,就好比失配,就让j往前等于next[j]
    //重复第一步,直到j等于零
    //j等于零,说明第一个字符都与第i个字符不相等
    int i = 1, j = 0;next[1] = 0;
    while(i < str.length())
    {
        if(j == 0 || str[i] == str[j]) {j++;i++;next[i] = j;}
        else j = next[j];
    }
}
int Index_Kmp(string str1, string str2, int pos = 1)
{
    int next[100];
    Get_Next(str2,next);
    int j = 1;
    while(pos < str1.length() && j < str2.length())
    {
        if(j == 0 || str1[pos] == str2[j]) {pos++;j++;}
        else j = next[j];
    }
    cout<<j<<" "<<pos;
    if(j == str2.length())
        return pos - j + 1;
    else
        return false;
}
int main()
{
    string str1, str2;
    cin>>str1>>str2;
    cout<<Index_Kmp(str1,str2);
    //#号不能删
    /*测试数据
        #acabaabaabcacaabc
        #abaabcac
    */
}

我也只是做个大概的总结,具体的,还是需要看书的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值