其他分享
首页 > 其他分享> > CodeForces 535D Tavas and Malekas

CodeForces 535D Tavas and Malekas

作者:互联网

洛谷传送门

CF 传送门

思路

首先如果给出的位置合法(即不会有重叠部分不相同的情况),答案为 \(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