#include<bits/stdc++.h> usingnamespace std; #define ll long long #define MAXN 1000005 intread(){ int x=0,f=1;char ch; do{ch=getchar();if(ch=='-') f=-1;} while(ch<'0'||ch>'9'); do{x=x*10+ch-48;ch=getchar();} while(ch>='0'&&ch<='9'); return x*f; }
int rt[MAXN], idx; int a[MAXN]; int n, m; structnode { int l, r, val; }tree[MAXN << 5];
intbuild(int l, int r){ int now = ++idx; if (l == r) { tree[now].val = a[l]; return now; } int mid = l + r >> 1; tree[now].l = build(l, mid); tree[now].r = build(mid + 1, r); return now; }
intupdate(int pre, int L, int R, int pos, int val){ int now = ++idx; tree[now] = tree[pre]; if (L == R && L == pos) { tree[now].val = val; return now; } int mid = L + R >> 1; if (pos <= mid) tree[now].l = update(tree[pre].l, L, mid, pos, val); else tree[now].r = update(tree[pre].r, mid + 1, R, pos, val); return now; }
intquery(int rt, int L, int R, int pos){ if (L == R) { return tree[rt].val; } int mid = L + R >> 1; if (pos <= mid) returnquery(tree[rt].l, L, mid, pos); elsereturnquery(tree[rt].r, mid + 1, R, pos); }
intmain(){ n = read(), m = read(); for (int i = 1; i <= n; i++) a[i] = read(); rt[0] = build(1, n); for (int i = 1; i <= m; i++) { int pre, opt, pos, val; pre = read(), opt = read(), pos = read(); if (opt == 1) { val = read(); rt[i] = update(rt[pre], 1, n, pos, val); } else { rt[i] = rt[pre]; printf("%d\n", query(rt[pre], 1, n, pos)); } } return0; }
扩展KMP
扩展 KMP 可以在O(N)时间内求出给定字符串每个后缀与该字符串前缀的最大匹配长度。类似的,也可以在O(N+M) 的时间内求出字符串 A 每个后缀与字符串 B 的最大匹配长度。
将 B 定义为模式串,类似于 KMP ,要先对 B 进行一遍自匹配。再利用求出来的 Z 函数进行 A 串与 B 串的匹配。
定义 t 为模式串(被匹配的字符串),s 为匹配串。
定义 Z 函数:z[i] 表示 t 和 t[i,m] (即以 t[i] 开头的后缀)的最长公共前缀的长度。定义边界 z[1]=0 。
#include"bits/stdc++.h" usingnamespace std; #define ll long long #define MAXN 200005 char s[MAXN]; char t[MAXN]; int n, m, q; int z[MAXN]; //模式串自我匹配 int p[MAXN]; //匹配串大小 int cnt[MAXN]; //匹配长度对应的cnt
voidgetZ(char t[], int m){ for (int l = 0, r = 0, i = 2; i <= m; i++) { if (i <= r) z[i] = min(z[i - l + 1], r - i + 1); while (z[i] < m && i + z[i] <= m && t[z[i] + 1] == t[i + z[i]]) z[i]++; if (i + z[i] - 1 > r) { l = i; r = i + z[i] - 1; } } }
intmain(){ cin >> n >> m >> q; scanf("%s", s + 1); scanf("%s", t + 1); getZ(t, m); //模式串自我匹配求Z函数 for (int l = 0, r = 0, i = 1; i <= n; i++) { if (i <= r) p[i] = min(z[i - l + 1], r - i + 1); while (p[i] < m && i + p[i] <= n && t[p[i] + 1] == s[i + p[i]]) p[i]++; if (i + p[i] - 1 > r) { l = i; r = i + p[i] - 1; } cnt[p[i]]++; } while (q--) { int len; cin >> len; printf("%d\n", cnt[len]); } return0; }
voidinit(){ int k = 0; b[k++] = '$', b[k++] = '#'; for (int i = 0; i < n; i++) b[k++] = a[i], b[k++] = '#'; b[k++] = '^'; n = k; }
voidmanacher(){ int mr = 0, mid; for (int i = 1; i < n; i++) { if (i < mr) p[i] = min(p[mid * 2 - i], mr - i); else p[i] = 1; while (b[i - p[i]] == b[i + p[i]]) p[i]++; if (i + p[i] > mr) { mr = i + p[i]; mid = i; } } }
intmain(){ scanf("%s", a); n = strlen(a); init(); manacher(); int res = 0; for (int i = 0; i < n; i ++ ) res = max(res, p[i]); printf("%d\n", res - 1); return0; }