Z函数 (扩展KMP)
Z函数 (扩展KMP)
-
这里只是口胡一下一些重要的点,想看图理解的可以去这里。我就是看这个题解学会的。
-
这里先留一个疑问,也是本篇博客所要解决的最大的问题,那就是第一种情况为什么是 而非
定义
-
表示 以 为起点的后缀和原串的
-
首先考虑求 的 函数,假设现在已经求完了的所有了。那么我们时刻维护一个 和 分别表示现在已知的所有函数里能扩展到的最远范围(除去), 为对应的左端点。
-
那么我们可以显然地发现和是相同的,同理 和 是相同的,我们设 表示, 那么我们发现和是想同的(因为就是的), 所以可以得到和是相同的,又因为我中存的都是最大的,所以就是我的一个候选项。
-
第一种情况也就是注意这里就是我开头问的问题,也就是第一个不等式为什么不取等。
- 当然首先,这种情况下显然我的。因为在以内,不可能再大。
- 我们考虑,现在的仅仅是我已知的最远距离而可能不是真正的最远距离,那么如果我在第一个不等式挂上等,相当于是强制现在的等于,不再给他机会向外扩展,但我的能到是因为你现在给我的最大范围是而不是我真正只能匹配到,也就是说我在现有的范围里已经完全匹配上了,到达边界了,我还应该继续向外扩展尝试,我是否能匹配更多,而不是停下,但是对于其他的无法触碰到的情况,我最大也就匹配成这样了,所以直接赋值是对的。
-
第二种情况就是了,显然我直接从开始暴力匹配就好了,复杂度不会退化,因为对于内层用于匹配的循环,每次执行最少加一,总共执行次,对于外层的是线性的遍历,所以总复杂度是的。
- 当然,这种情况更新之后,我的一定是一个更加优秀的记得更新,否则会退化成
Code
here
#include <bits/stdc++.h>
#define Re register int
#define LL long long
#define LD double
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define fr(x, y, z) for(Re x = y; x <= z; x ++)
#define fp(x, y, z) for(Re x = y; x >= z; x --)
#define delfr(x, y, z) for(Re x = y; x < z; x ++)
#define delfp(x, y, z) for(Re x = y; x > z; x --)
#define ki putchar(10)
#define fk putchar(' ')
#define mes(x, y) memset(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define WMX aiaiaiai~~
using namespace std;
namespace kiritokazuto {
fuc(char, getc)(){
static char buf[1 << 18], *p1, *p2;
if(p1 == p2){
p1 = buf, p2 = buf + fread(buf, 1, 1 << 18, stdin);
if(p1 == p2)return EOF;
}
return *p1++;
}
fuc(LL, read)() {
LL x = 0, f = 1;char c = getc();
while(!isdigit(c)){if(c == '-')f = -1; c = getc();}
while(isdigit(c)){x = (x << 1) + (x << 3) + (c ^ 48); c = getc();}
return x * f;
}
template <typename T> fuc(void, write)(T x){
if(x < 0)putchar('-'), x = -x;
if(x > 9)write(x / 10);putchar(x % 10 | '0');
}
}
using namespace kiritokazuto;
const int maxn = 2e7 + 50000, Inf = 200000000, Mod = 998244353, lim = 2e5 ;
LL z[maxn], ext[maxn];
char t[maxn], s[maxn];
fuc(void, getz)(char *s) {
LL len = strlen(s);
LL k = 1, r = 0, l = 0;//0为本身,所以从1
z[0] = len;
while(r + 1 < len && s[r] == s[k + r])r++;//初始值
z[1] = r;
delfr(i, 2,len) {//1处理完,所以是二
r = k + z[k] - 1;//最远边界
l = z[i - k];
if(i + l <= r) z[i] = l;
else {
LL j = max(0 * 1ll, r - i + 1);
while(j + 1 < len && s[i + j] == s[j])j++;
z[i] = j;
k = i;
}
}
// delfr(i, 0, len) {
// printf("nxt[%d] = %d\n", i, z[i]);
// }
}
fuc(void, getext)(char *s, char *t) {
LL n = strlen(s), m = strlen(t);
LL r = 0, l = 0, k = 0;
while(r < n && r < m && t[r] == s[r])r++;
ext[0] = r;
delfr(i, 1, m) {
l = z[i - k];
r = k + ext[k] - 1;
if(i + l <= r)ext[i] = l;
else {
LL j = max(0 * 1ll, r - i + 1);
while(j < n && i + j < m && t[i + j] == s[j])j++;
ext[i] = j;
k = i;
}
}
// delfr(i, 0, m) {
// printf("ext[%d] = %d\n", i, ext[i]);
// }
}
LL ans = 0;
signed main() {
scanf("%s %s", t, s);
getz(s);
getext(s, t);
LL n = strlen(s), m = strlen(t);
delfr(i, 0, n) ans = (ans ^ (i + 1) * (z[i] + 1));
write(ans), ki;
ans = 0;
delfr(i, 0, m) ans = (ans ^ (i + 1) * (ext[i] + 1));
write(ans);
return 0;
}
作者: kiritokazuto
出处:https://www.cnblogs.com/kiritokazuto/p/16875016.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现