\(\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
标签:nxt,AC,noi,10.6,int,T1,kmp,模拟
From: https://www.cnblogs.com/into-qwq/p/16757710.html