KMP模板

欢迎点赞,评论

题目:https://www.luogu.com.cn/problem/P3375

第一次匹配成功之后 j 的位置 回溯到 ne[] 数组记录的前面已经匹配的长度(第一次匹配成功

则前三个字母ABA一定是匹配的 所以 j 回溯到A所在的位置 此时比对的是 j + 1)

定义一个字符串s的 border 为s的一个非 s本身的子串 t,满足t既是s的 前缀,又是s的 后缀
最后一行输出 |s2|个整数,第 i个整数表示s2的长度为 i的前缀的最长 border 长度。

理解为s的每个 从前自后 每次在末尾增加一个字母的 子串

例:BABABAC 即 B BA BAB BABA ...

border 即s2每个子串的最长公共前后缀 ➡ ne[]数组

#include <bits/stdc++.h>

using namespace std;

const int N = 1000010;

char s[N],p[N];
int ne[N];

int main()
{
    cin >> s + 1;
    cin >> p + 1;
    int n = strlen(s + 1),m = strlen(p + 1);
    
    // ne[]数组
    for(int i = 2,j = 0;i <= m;i++)
    {
        while(j && p[i] != p[j + 1]) j = ne[j];//同KMP匹配过程
        if(p[i] == p[j + 1]) j++;
        ne[i] = j; // 不同的是 每次移动i前 将i前面已经匹配的长度记录到ne[]数组中
    }
    
    for(int i = 1,j = 0;i <= n;i++) // 从 1 开始
    {
        while(j && s[i] != p[j + 1]) j = ne[j];
        if(s[i] == p[j + 1]) j++; // j 是指针
        if(j == m)
        {
            cout << i - m + 1 << endl; //指针 j 指的是往后一位 所以 i - m + 1 就是第几位
            j = ne[j];
        }
    }
    
    for(int i = 1;i <= m;i++) cout << ne[i] << ' ';
    
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值