逸一时,误一世!|

MistZero

园龄:5年5个月粉丝:8关注:3

KMP 和扩展 KMP

给定一个字符串 s[1n]

定义前缀函数 fi 表示 s[1i] 最长的相等的真前缀与真后缀的长度。

规定 f1=0

发现 fi 至多为 fi1+1(匹配了 i 上的字符)。

考虑 i 上的字符不匹配的情况。

那么找到第二长的满足真前缀 = 真后缀的位置一定最优。

然后会发现这玩意儿其实就是前缀数组的定义。

直接不断跳前缀数组即可。

#include <bits/stdc++.h>
using namespace std;

const int N = 3e6 + 10;
string s, t, g; int f[N];

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    cin >> s >> t; g = "$" + t + "#" + s;
    int len = g.size() - 1, lent = t.size();
    for (int i = 2; i <= len; ++i) {
        int pos = i - 1;
        while (pos && g[f[pos] + 1] ^ g[i]) pos = f[pos];
        if (g[f[pos] + 1] == g[i]) f[i] = f[pos] + 1;
        if (f[i] == lent) cout << i - 2 * lent << endl;
    }
    for (int i = 1; i <= lent; ++i) cout << f[i] << ' ';
    return cout << endl, 0;
}

那么扩展 KMP 其实和这个类似。

定义 zi 表示 ss[in] 的 LCP(最长公共前缀)长度。

实时维护一个区间 [l,r] 表示当前能匹配的右端点最右的区间。

那么由定义有 s[1rl+1]=s[lr]

  • 如果当前 ir

那么易得 s[ir]=s[il+1rl+1]

根据 zil+1,得到 sil+1 开头的后缀的 LCP 长度。

那么,若 zil+1<ri+1,那么表示能匹配的长度至多为 zil+1

否则直接暴力向后匹配,更新 l,r

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 4e7 + 10;
string a, b, s; int l, r, resz, resp, z[N];

signed main() {
    ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    cin >> a >> b; s = "#" + b + "$" + a;
    int len = s.size() - 1, lena = a.size(), lenb = b.size();
	z[1] = lenb, l = r = 1;
    for (int i = 2; i <= len; ++i) {
        if (i <= r && z[i - l + 1] < r - i + 1) z[i] = z[i - l + 1];
        else {
            z[i] = max(0ll, r - i + 1);
            while (i + z[i] <= len && s[z[i] + 1] == s[i + z[i]]) ++z[i];
        }
        if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
    }
    for (int i = 1; i <= lenb; ++i) resz ^= (i * (z[i] + 1));
    for (int i = 1; i <= lena; ++i) resp ^= (i * (z[i + lenb + 1] + 1));
    return cout << resz << endl << resp << endl, 0;
}

本文作者:MistZero

本文链接:https://www.cnblogs.com/MistZero/p/KMP.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   MistZero  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起