Codeforces 536B Tavas and Malekas kmp找所有与前缀匹配的后缀

题目链接

题意

有只含小写字母的字符串 T ,其中出现了若干次字符串 P ,并升序给出其中一部分 P 的起始位置,要求 T 有多少种不同的可能。

思路

就是找有多少空缺位置 k ,答案就是 26k .

按顺序把 P T 中填充,同时记录空缺位置。此时需要判断是否与之前已填充的部分矛盾,其实就是判断给定的 P 的前缀与后缀是否匹配。

直接比较显然会 tle . 故应预处理出 P 的所有与前缀相匹配的后缀的位置。这里就要再一次用到 fail 数组。

考虑 fail[len] 的含义,意味着串
A: [0..fail[len]1]

B: [lenfail[len],len1]
匹配。
所以 lenfail[len] 位置处与前缀匹配。

再沿着 fail[len] 往前跳,记 fail[len]=k ,于是跳到 k 位置处。
fail[k] 的含义为串
A: [0..fail[k]1]

B: [kfail[k],k1]
匹配,

B: [kfail[k],k1]

C: [kfail[k]+lenk,len1]
匹配,
所以 kfail[k]+lenk=lenfail[k] 位置处与前缀匹配。

这样迭代下去, P 的所有与前缀相匹配的后缀的位置就能找到了。

Code

#include 
#define maxn 1000010
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
set<int> st;
int f[maxn], n, m, a[maxn], len;
char s[maxn], P[maxn];
LL poww(LL a, LL b) {
    LL ret = 1;
    while (b) {
        if (b & 1) (ret *= a) %= mod;
        (a *= a) %= mod;
        b >>= 1;
    }
    return ret;
}
void getfail() {
    f[0] = f[1] = 0;
    for (int i = 1; i < len; ++i) {
        int j = f[i];
        while (j && P[j] != P[i]) j = f[j];
        f[i+1] = P[i] == P[j] ? j+1 : 0;
    }
    int temp = len;
    while (f[temp]) {
        st.insert(len - f[temp]);
        temp = f[temp];
    }
}
void getdata() {
    printf("%s\n", P);
    for (int i = 0; i < m; ++i) printf("%d ", a[i]+1);
}
int main() {
    freopen("in.txt", "r", stdin);
    scanf("%d%d%s", &n, &m, P);
    len = strlen(P);
    getfail();
    int cur = 0, emp = 0;
    bool flag = false;
    for (int i = 0; i < m; ++i) scanf("%d", &a[i]), --a[i];
    for (int i = 0; i < m; ++i) {
        if (cur <= a[i]) {
            emp += a[i] - cur;
            cur = a[i] + len;
        }
        else {
            if (st.count(len-(cur-a[i]))) cur = a[i] + len;
            else {
                flag = true;
                break;
            }
        }
    }
    emp += n - cur;
    if (flag) printf("0\n");
    else printf("%I64d\n", poww(26, emp));
    return 0;
}

后记

不知道为什么一直 tle ,后来发现写的时候不知道为什么每次都把 P strcpy 到了相应的位置…不 T 才有鬼(x

你可能感兴趣的:(kmp,字符串,Codeforces)