2022CCPC Online Contest E - Substring Match
利用大写字母较少的性质,记录两个大写字母中间的串是否相等来进行转移。
设 \(f[i][j]\) 表示考虑用到第 \(i\) 个大写字母的时候,\(s\) 匹配到第 \(j\) 个字符时最长匹配数。
-
当前大写字母 \(t[pos[i]] = s[j]\) 时,显然有 \(f[i][j] = f[i][j - 1] + 1\)
-
如果 \(s[pos[i - 1] + 1 \sim pos[i] - 1] = t[pos[i - 1] + 1 \sim pos[i] - 1]\),必然有 \(f[i][j] = \max(f[i][j], \, f[i - 1][pos[i - 1]]\)
具体参见代码,时间复杂度 \(O(200|S|)\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e5 + 10, base = 331, INF = 1e9;
int n, m, pos[210], cnt, f[210][N];
char s[N], t[N];
ull pw[N], hs[N], val[N];
void solve() {
cin >> s + 1 >> t + 1, cnt = 0;
pw[0] = 1, n = strlen(s + 1), m = strlen(t + 1);
for(int i = 1; i < N; i ++ ) pw[i] = pw[i - 1] * base;
for (int i = 1; i <= n; i ++ ) hs[i] = hs[i - 1] * base + s[i];
ull x = 0;
for (int i = 1; i <= m + 1; i ++ ) {
if (i == m + 1 || isupper(t[i])) {
t[i] = t[i] - 'A' + 'a';
pos[ ++ cnt] = i;
val[cnt] = x;
x = 0;
} else x = x * base + t[i];
}
int ans = 0;
for (int i = 1; i <= cnt; i ++ ) {
for (int j = 0; j <= n; j ++ ) {
f[i][j] = -INF;
if (j && t[pos[i]] == s[j]) f[i][j] = f[i][j - 1] + 1;
int len = pos[i] - pos[i - 1] - 1;
if (j >= len && (!len || hs[j] - hs[j - len] * pw[len] == val[i])) {
f[i][j] = max(f[i][j], f[i - 1][j - len] + len);
}
if (i == cnt) ans = max(ans, f[i][j]);
}
}
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while (T -- ) solve();
return 0;
}