CF955D Scissors

CF955D Scissors

给出两个串 \(s\)\(t\) , 从 \(s\) 中取出两段不重的, 长度为 \(k\) 的串拼接起来, 判断是否存在一种方案使得 \(t\) 是拼接串的子串.

\(Hash\) , 处理出每个 \(t\) 前缀在 \(s\) 中出现的最早位置以及每个 \(t\) 后缀在 \(s\) 中出现的最晚位置.

然后 \(O(n)\) 扫一遍就行了.

\(code:\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 5e5 + 5;
ll mod = 1e9, base = 30;
int n, m, k, ans1, ans2, lm[N], rm[N];
char s[N], t[N];
struct Hash {
    ll Hash[N], pw[N];
    void hs(char *s) {
        int len = strlen(s + 1);
        pw[0] = 1;
        for (int i = 1; i <= len; i++) {
            Hash[i] = (Hash[i - 1] * base + s[i] - 'a' + 1) % mod;
            pw[i] = pw[i - 1] * base % mod;
        }
    }
    ll get(int l, int r) {
        return ((Hash[r] - Hash[l - 1] * pw[r - l + 1]) % mod + mod) % mod;
    }
} S, T;
bool Judge() {
    if (n < (k << 1) || m > (k << 1)) return false;
    S.hs(s), T.hs(t);
    int pos = k;
    for (int i = 1; i <= m; i++) lm[i] = n + 1;
    for (int i = 1; i <= min(m, k); i++) {
        while (pos <= n && S.get(pos - i + 1, pos) != T.get(1, i)) pos++;
        if (S.get(k - i + 1, k) == T.get(1, i)) pos = k;
        lm[i] = pos;
    }
    pos = n - k + 1;
    for (int i = 1; i <= min(m, k); i++) {
        while (pos && S.get(pos, pos + i - 1) != T.get(m - i + 1, m)) pos--;
        if (S.get(n - k + 1, n - k + i) == T.get(m - i + 1, m)) pos = n - k + 1;
        rm[m - i + 1] = pos;
    }
    for (int i = 1; i <= n - m + 1; i++) {
        if (S.get(i, i + m - 1) == T.get(1, m)) {
            if (k >= i && n - k + 1 <= i + m - 1) continue;
            ans1 = min(max(1, i - k + 1), n - k + 1 - k);
            ans2 = max(k + 1, min(n - k + 1, i));
            return true;
        }
    }
    for (int i = 1; i < m; i++) {
        if (lm[i] < rm[i + 1] && lm[i] <= n && rm[i + 1]) {
            ans1 = lm[i] - k + 1, ans2 = rm[i + 1];
            return true;
        }
    }
    return false;
}
int main() {
    srand(time(NULL));
    mod += rand(), base += rand() % 10;
    n = read(), m = read(), k = read();
    scanf("%s%s", s + 1, t + 1);
    if (Judge()) printf("Yes\n%d %d", ans1, ans2);
    else printf("No\n");
    return 0;
}
posted @ 2021-09-03 10:40  sshadows  阅读(36)  评论(0编辑  收藏  举报