Codeforces 536B Tavas and Malekas 求自身首尾的重叠位置 KMP

来源:互联网 发布:mysql删除表字段 编辑:程序博客网 时间:2024/06/10 02:10

题目链接:点击打开链接

题意:

用小写字母构造n长的串S,m个要求

字符串P

下面m个位置。a1, a2···am(输入有序)

要使得字符串S的以ai 开头且后面是一个P串。

问构造的方法数

思路:

实际上,对于ai, ai+1 ,两个位置,如果这两个位置会相互影响(即 ai+1 - ai < len) 

复制一个和P一样的串P‘

把P放在ai位置,把P‘放在ai+1位置,那么只需要判断一下 P的后半段是否和P‘的前半段匹配即可。

也就是P’的哪些位置是和P的尾部相同的。

KMP求出这些位置放到set里。

然后就是简单的判断了

#include <stdio.h>#include <string.h>#include <string>#include <math.h>#include <map>#include <vector>#include <set>#include <algorithm>#include <iostream>using namespace std;template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> pii;const int N = 1e6 + 10;const int mod = 1e9 + 7;int f2[N], len;char s1[N], s2[N];void getFail(int *f, char *P){f[0] = f[1] = 0;for (int i = 1; i < len; i++){int j = f[i];while (j&&P[i] != P[j])j = f[j];f[i + 1] = P[i] == P[j] ? j + 1 : 0;}}set<int>s;void KMP(int *f, char *S1, char *S2){getFail(f, S2);int j = 0, i = 0;while (i <= len){while (j && S1[i] != S2[j]) j = f[j];i++, j++;}for (int i = len; f[i]; i = f[i])s.insert(len-f[i]);}int m, n;bool v[N];int main() {while (cin >> n){rd(m);scanf("%s", s1);while (m--){int u; rd(u);v[u] = true;}len = strlen(s1);memcpy(s2, s1, sizeof s1);KMP(f2, s1, s2);ll ans = 1;for (int i = 1, last = -1e7; i <= n; i++){if (v[i] == false && i - last >= len){ans *= 26LL;if (ans >= mod)ans %= mod;}else if (v[i] == true){if (i - last < len && !s.count(i-last)){ans = 0; break;}last = i;}}pt(ans%mod); puts("");}return 0;}


0 0
原创粉丝点击