CodeForces 535D Tavas and Malekas
作者:互联网
思路
首先如果给出的位置合法(即不会有重叠部分不相同的情况),答案为 \(26^c\),\(c\) 为未填的字符数量。
于是本题的重点是判断是否有重叠部分不相同的情况。不难发现我们只用检验相邻的位置重叠部分是否相同。\(i \in [2,n]\),令 \(d = a_i - a_{i-1}\),只用判断模式串后缀 \([d+1,len]\) 和整个串的 LCP 长度是否为 \(n-i\)。可以预处理出模式串的 \(\mathbf{Z}\) 函数数组 \(nxt\),判断 \(d + nxt_{d+1}\) 是否 \(= n\) 即可。注意特判 \(m=0\) 的情况。
时空复杂度均为 \(O(n)\)。
代码
code
/*
p_b_p_b txdy
AThousandMoon txdy
AThousandSuns txdy
hxy txdy
*/
#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
const int maxn = 1000100;
const ll mod = 1000000007;
int n, m, a[maxn], nxt[maxn];
char s[maxn];
void solve() {
scanf("%d%d%s", &n, &m, s + 1);
if (m == 0) {
ll ans = 1;
for (int i = 0; i < n; ++i) {
ans = ans * 26 % mod;
}
printf("%lld\n", ans);
return;
}
for (int i = 1; i <= m; ++i) {
scanf("%d", &a[i]);
}
int len = strlen(s + 1);
nxt[1] = len;
for (int i = 2, l = 0, r = 0; i <= len; ++i) {
nxt[i] = (i > r) ? 0 : min(nxt[i - l + 1], r - i + 1);
while (s[nxt[i] + 1] == s[nxt[i] + i]) {
++nxt[i];
}
if (i + nxt[i] - 1 > r) {
l = i;
r = i + nxt[i] - 1;
}
}
ll ans = 1;
for (int i = 2; i <= m; ++i) {
int d = a[i] - a[i - 1];
if (d >= len) {
for (int j = 0; j < d - len; ++j) {
ans = ans * 26 % mod;
}
continue;
}
if (d + nxt[d + 1] < len) {
puts("0");
return;
}
}
for (int i = a[m] + len; i <= n; ++i) {
ans = ans * 26 % mod;
}
for (int i = 1; i < a[1]; ++i) {
ans = ans * 26 % mod;
}
printf("%lld\n", ans);
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
标签:nxt,txdy,int,ll,CodeForces,len,Tavas,535D,ans 来源: https://www.cnblogs.com/zltzlt-blog/p/16400266.html