CF822E Liar 题解
CF822E Liar 题解
考虑 $f_{i, j} $ 表示香肠前 \(i\) 个字符被分割为 \(j\) 段,最多能匹配希望得到的字符串多少位。
转移分两种,第一种 \(f_{i, j} \rightarrow f_{i + 1, j}\),第二种 \(f_{i, j} + lcp\rightarrow f_{i + lcp, j + 1}\),其中 \(lcp = LCP(s_{i + 1}, t_{f_{i, j} + 1})\)。
算 \(LCP\) 可以用后缀数组或哈希表,分别做到 \(O(nx)\) 和 \(O(nx\log n)\)。
// Problem: J - Liar
// Author: Moyou
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 2e5 + 10;
struct SuffixA {
int n, idx, sig, sa[N], sa2[N << 1], tmp[N << 1], buc[N], rk[N << 1], x[N], ht[N], lg[N], st[22][N];
void init(string s) {
n = s.size(), s = " " + s;
sig = 128, idx = 0;
for(int i = 1; i <= n; i ++) buc[rk[i] = s[i]] ++;
for(int i = 1; i <= sig; i ++) buc[i] += buc[i - 1];
for(int i = n; i; i --) sa[buc[rk[i]] --] = i;
for(int j = 1; idx < n; j <<= 1, sig = idx) {
idx = 0; for(int i = n - j + 1; i <= n; i ++) sa2[++ idx] = i;
for(int i = 0; i <= sig; i ++) buc[i] = 0;
for(int i = 1; i <= n; i ++) {
if(sa[i] > j) sa2[++ idx] = sa[i] - j;
buc[rk[i]] ++;
}
for(int i = 1; i <= sig; i ++) buc[i] += buc[i - 1];
for(int i = n; i; i --) sa[buc[rk[sa2[i]]] --] = sa2[i], tmp[i] = rk[i];
idx = 0;
for(int i = 1; i <= n; i ++)
rk[sa[i]] = ((tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + j] == tmp[sa[i - 1] + j]) ? idx : ++ idx);
}
for(int i = 1, l = 0; i <= n; i ++) {
if(l) l --;
while(s[i + l] == s[sa[rk[i] - 1] + l]) l ++;
ht[rk[i]] = l;
}
}
void ST() {
for(int i = 2; i <= n; i ++) lg[i] = lg[i >> 1] + 1;
for(int i = 1; i <= n; i ++) st[0][i] = ht[i];
for(int i = 1; i <= lg[n]; i ++)
for(int j = 1; j + (1 << i) - 1 <= n; j ++)
st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << i - 1)]);
}
int LCP(int i, int j) {
if(i > j) swap(i, j); i ++;
if(i <= 1 || j > n) return 0;
int k = lg[j - i + 1];
return min(st[k][i], st[k][j - (1 << k) + 1]);
}
} sa;
int n, m, k, f[N][35];
string s, t;
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> s >> m >> t >> k;
string S = s + '#' + t;
sa.init(S), sa.ST();
memset(f, -0x3f, sizeof f);
f[0][0] = 0;
for(int i = 0; i < n; i ++) {
for(int j = 0; j <= k; j ++) {
if(f[i][j] >= 0) {
f[i + 1][j] = max(f[i + 1][j], f[i][j]);
int lcp = sa.LCP(sa.rk[i + 1], sa.rk[n + 2 + f[i][j]]);
if(j < k) f[i + lcp][j + 1] = max(f[i + lcp][j + 1], f[i][j] + lcp);
}
}
}
for(int j = 0; j <= k; j ++) {
if(f[n][j] == m) {
cout << "YES\n";
return 0;
}
}
cout << "NO\n";
return 0;
}

QwQ
浙公网安备 33010602011771号