Loading

10.6 noi(p) 模拟赛

\(\rm NOIP\) 模拟赛

\(\rm Date: 10.6\)

去掉 T1 可以当省选练习题了(当然 T4 放 T1)

\(T1\)

哈希即可,也有贪心的做法,但是自然溢出被卡了

\(T2\)

如果是一条链,那么这个操作就是交换前缀和,但是这个结论不能套用到环上。可以把环想象为一个无限长的序列,但是不会维护

摆了

\(T3\)

大概是广义 SAM 建 fail 树跑树剖。

\(T4\)

显然先求一个 kmp,然后令 \(nxt[i]\) 表示在 \(i\) 处失配会跳到哪里,\(f[i]\) 表示配上了前 \(i\) 为的期望答案。那么考虑前 \(i-1\) 已经配上了,第 \(i\) 位有可能配上也有可能失配,即 \(f[i-1]\to f[i], f[i-1]\to f[nxt[i-1]]\)。那么有方程 \(f[i]=2+f[i-1]-f[nxt[i-1]]-2\)。设 \(f[0]=x\) (答案),那么 \(f[i]\) 全程系数为 \(1\),求出 \(f[n]\) 的常数项即可解出 \(x\)

\(nxt[i]\) 可以用 \(kmp[]\) 路径压缩也可以用AC自动机。

#include <bits/stdc++.h>
#define AC_auto 0
#define KMP 9
using namespace std;
const int N = 1e6 + 5, mod = 1e9 + 7;

char s[N];
int n, nxt[N][2], kmp[N];
int f[N];

#if AC_auto
void build() {
    nxt[0][s[1] - '0'] = 1;
    for(int i = 1; i < n; ++i) {
        nxt[i][s[i + 1] - '0'] = i + 1;
        if(i == 1) kmp[i] = 0;
        else kmp[i] = nxt[kmp[i - 1]][s[i] - '0'];
        if(!nxt[i][0]) nxt[i][0] = nxt[kmp[i]][0];
        if(!nxt[i][1]) nxt[i][1] = nxt[kmp[i]][1];
    }
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("Ans.txt", "w", stdout);
#endif
    scanf("%s", s + 1), n = strlen(s + 1);
    build();
    for(int i = 1; i <= n; ++i) 
        f[i] = (2LL * f[i - 1] - f[nxt[i - 1][(s[i] - '0') ^ 1]] - 2) % mod;
    printf("%lld", (mod - f[n]) % mod);
}
#endif
#if KMP
signed main() {
    scanf("%s", s + 1), n = strlen(s + 1);
    for(int i = 2, j = 0; i <= n; ++i) {
        while(j && s[j + 1] != s[i]) j = kmp[j];
        if(s[j + 1] == s[i]) ++j;
        kmp[i] = j;
    }
    for(int i = 1; i <= n; ++i) {
        while(s[kmp[i - 1] + 1] == s[i] && kmp[i - 1]) kmp[i - 1] = kmp[kmp[i - 1]];
        if(!kmp[i - 1]) f[i] = (2LL * f[i - 1] - 2) % mod;
        else f[i] = (2LL * f[i - 1] - f[kmp[i - 1] + 1] - 2) % mod;
    }
}
#endif
posted @ 2022-10-06 15:23  Into_qwq  阅读(27)  评论(1编辑  收藏  举报