【luogu P5410】【模板】扩展 KMP(Z 函数)(字符串)

【模板】扩展 KMP(Z 函数)

题目链接:luogu P5410

题目大意

给你一个字符串,要你求它每个后缀跟它 LCP 的长度。(Z 函数)
给你两个字符串,要你求一个字符串每个后缀跟另一个字符串 LCP 的长度。(exKMP)

思路

这个东西感觉有点马拉车的感觉。

考虑知道了当前的答案 z1i1,考虑怎么求 zi
首先我们肯定是找到一个可以匹配的串 [l,r],那肯定是找 r 最大的,记录当前是 l,r

然后如果 ir,我们考虑利用它,通过证明可以得到 rimin(ri+1,ril+1)
证明考虑逐位证,设 1xmin(ri+1,ril+1)
si+x1=sl+(i+xl)1
=s1+(i+xl)1=si+xl(左边的限制条件)
=s1+(il+1)+x
=s1+x(当 xzil+1

然后我们再暴力扩展,然后维护最大 r 对于的 l,r
然后每个数只会别暴力扩展一次,所以复杂度是 O(n)

至于两个字符之间的 exKMP,我们就一样的匹配法。

代码

#include<cstdio> #include<cstring> #include<iostream> #define ll long long using namespace std; const int N = 2e7 + 5; char a[N], b[N]; int an, bn, z[N], p[N]; ll ans; void get_Z(char *s, int n) { for (int i = 1; i <= n; i++) z[i] = 0; z[1] = n; for (int i = 2, l = 0, r = 0; i <= n; i++) { if (i <= r) z[i] = min(z[i - l + 1], r - i + 1); while (i + z[i] <= n && s[i + z[i]] == s[1 + z[i]]) z[i]++; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } } void exKMP(char *a, int n, char *b, int m) { for (int i = 1; i <= n; i++) p[i] = 0; for (int i = 1, l = 0, r = 0; i <= n; i++) { if (i <= r) p[i] = min(z[i - l + 1], r - i + 1); while (i + p[i] <= n && a[i + p[i]] == b[1 + p[i]]) p[i]++; if (i + p[i] - 1 > r) l = i, r = i + p[i] - 1; } } int main() { scanf("%s", a + 1); scanf("%s", b + 1); an = strlen(a + 1); bn = strlen(b + 1); get_Z(b, bn); ans = 0; for (int i = 1; i <= bn; i++) ans ^= 1ll * i * (z[i] + 1); printf("%lld\n", ans); exKMP(a, an, b, bn); ans = 0; for (int i = 1; i <= an; i++) ans ^= 1ll * i * (p[i] + 1); printf("%lld", ans); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_P5410.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示