KMP模板

    先推荐个很好的博客,我对KMP的理解是基于这篇博客的。

    KMP是用来求串的最大匹配。

    KMP是通过对模式串的处理,获得前i个字符的相同的最大前缀和最大后缀。如果前缀与后缀一样,那么匹配会达到这种效果:

                

这样前面匹配的得到的子串在后续匹配中仍能使用,这时我们只需要for循环目标串,如果比较到不匹配的地方,模式串直接偏移相对应的最大前缀部分,达到了n + m的效果。光看着肯定蒙,用笔模拟过程才是硬道理。

HDU 1686

题意就是先给一个T,表示T组数据,然后每一组输入一个str1, str2。str2里能匹配多少个str1.

include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <string.h>

using namespace std;

string s1, s2;
int Next[10005];  //用来处理前i个字符相同的最大前缀和最大后缀,-1表示没有, 0, 表示一个,以此类推。
int ans;


void getnext()   //处理模式串,得到NEXT【i】。
{
    int k = -1;
    Next[0] = -1;
    int len = s1.length();
    for(int i = 1; i < len; i++)
    {
        while(k != -1 && s1[i] != s1[k + 1])  //这一步可以说是kmp里最难理解的,其实就是如果他们前i个有相同的前缀和后缀,
        {                                      //但是此时的字符又不匹配,怎么办,我们可以从之前匹配的再找,比如序列32231
            k = Next[k];                       //next[3] = 0; 那么接下来是2 和 1比较,发现不相等,怎么办,我们可以找前k个的,因为
        }                                      //如果k != -1,那么前k个字符前面和后面都有next【k】个相等,相对应的后k个字符也一样,
        if(s1[i] == s1[k + 1])                 //相当于在i的范围内可以划成四个部分1 2 3 4, 12 = 34, 1 = 2, 所以1 = 4.所以继续比较。
        {
            k += 1;
        }
        Next[i] = k;
    }
}


void kmp()
{
    int k = -1;
    int len1 = s1.length();
    int len2 = s2.length();
    for(int i = 0; i < len2; i++)
    {
        while(k != -1 && s2[i] != s1[k + 1])  //思想同上,不过这个只需要计数就好
        {
            k = Next[k];
        }
        if(s2[i] == s1[k + 1])
        {
            k += 1;
        }
        if(k == len1 - 1)
        {
            ans += 1;
        }
    }
}


int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        ans = 0;
        memset(Next, -1, sizeof(Next));
        cin >> s1 >> s2;
        getnext();
        kmp();
        cout << ans << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值