2022CCPC Online Contest E - Substring Match

image

利用大写字母较少的性质,记录两个大写字母中间的串是否相等来进行转移。

\(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;
}
posted @ 2025-03-27 23:03  YipChip  阅读(39)  评论(0)    收藏  举报