专栏文章

题解:P5410 【模板】扩展 KMP/exKMP(Z 函数)

P5410题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miora3yj
此快照首次捕获于
2025/12/02 23:51
3 个月前
此快照最后确认于
2025/12/02 23:51
3 个月前
查看原文
考虑利用 1j<i,z(j)1\le j<i,z(j) 递推出 z(i)z(i)
需要维护 [l,r][l,r]r=maxj=1i1j+z(j)1r=\max\limits_{j=1}^{i-1} j+z(j)-1llrr 的取值对应的 jj
ext(i)ext(i) 同理。
每次要么 O(1)O(1) 转移,要么 rr 至少 +1+1,复杂度 O(n)O(n)
CPP
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using UI = unsigned int;
using ULL = unsigned long long;
using DB = double;
using LDB = long double;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
#define CP(x) complex<x>
#define fst first
#define snd second
#define popcnt(i) __builtin_popcount(i)

const int N = 2e7 + 5;

int n, m;
string a, b;
int z[N], ext[N];

void exKMP() {
    int l = 0, r = 0;
    z[1] = m;
    for (int i = 2; i <= m; i++) {
        if (i > r) {
            z[i] = 0;
            while (i + z[i] <= m && b[z[i] + 1] == b[i + z[i]]) {
                ++z[i];
            }
            l = i, r = i + z[i] - 1;
        } else if (z[i - l + 1] < r - i + 1) {
            z[i] = z[i - l + 1];
        } else {
            z[i] = r - i + 1;
            while (i + z[i] <= m && b[z[i] + 1] == b[i + z[i]]) {
                ++z[i];
            }
            l = i, r = i + z[i] - 1;
        }
    }
    l = 0, r = 0;
    for (int i = 1; i <= n; i++) {
        if (i > r) {
            ext[i] = 0;
            while (ext[i] < m && i + ext[i] <= n && b[ext[i] + 1] == a[i + ext[i]]) {
                ++ext[i];
            }
            l = i, r = i + ext[i] - 1;
        } else if (z[i - l + 1] < r - i + 1) {
            ext[i] = z[i - l + 1];
        } else {
            ext[i] = r - i + 1;
            while (ext[i] < m && i + ext[i] <= n && b[ext[i] + 1] == a[i + ext[i]]) {
                ++ext[i];
            }
            l = i, r = i + ext[i] - 1;
        }
    }
}

void solve() {
    cin >> a >> b;
    n = a.size(), m = b.size();
    a = ' ' + a, b = ' ' + b;
    
    exKMP();

    LL ans1 = 0, ans2 = 0;
    for (int i = 1; i <= m; i++) ans1 ^= (LL)i * (z[i] + 1);
    for (int i = 1; i <= n; i++) ans2 ^= (LL)i * (ext[i] + 1);
    cout << ans1 << '\n' << ans2 << '\n';
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) solve();
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...