题目链接
题意
有只含小写字母的字符串
T
,其中出现了若干次字符串
思路
就是找有多少空缺位置
k
,答案就是
按顺序把
P
往
直接比较显然会
考虑
fail[len]
的含义,意味着串
A:
[0..fail[len]−1]
与
B:
[len−fail[len],len−1]
匹配。
所以
len−fail[len]
位置处与前缀匹配。
再沿着
fail[len]
往前跳,记
fail[len]=k
,于是跳到
k
位置处。
A:
[0..fail[k]−1]
与
B:
[k−fail[k],k−1]
匹配,
而
B:
[k−fail[k],k−1]
与
C:
[k−fail[k]+len−k,len−1]
匹配,
所以
k−fail[k]+len−k=len−fail[k]
位置处与前缀匹配。
这样迭代下去, P 的所有与前缀相匹配的后缀的位置就能找到了。
Code
#include <bits/stdc++.h>
#define maxn 1000010
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
set<int> st;
int f[maxn], n, m, a[maxn], len;
char s[maxn], P[maxn];
LL poww(LL a, LL b) {
LL ret = 1;
while (b) {
if (b & 1) (ret *= a) %= mod;
(a *= a) %= mod;
b >>= 1;
}
return ret;
}
void getfail() {
f[0] = f[1] = 0;
for (int i = 1; i < len; ++i) {
int j = f[i];
while (j && P[j] != P[i]) j = f[j];
f[i+1] = P[i] == P[j] ? j+1 : 0;
}
int temp = len;
while (f[temp]) {
st.insert(len - f[temp]);
temp = f[temp];
}
}
void getdata() {
printf("%s\n", P);
for (int i = 0; i < m; ++i) printf("%d ", a[i]+1);
}
int main() {
freopen("in.txt", "r", stdin);
scanf("%d%d%s", &n, &m, P);
len = strlen(P);
getfail();
int cur = 0, emp = 0;
bool flag = false;
for (int i = 0; i < m; ++i) scanf("%d", &a[i]), --a[i];
for (int i = 0; i < m; ++i) {
if (cur <= a[i]) {
emp += a[i] - cur;
cur = a[i] + len;
}
else {
if (st.count(len-(cur-a[i]))) cur = a[i] + len;
else {
flag = true;
break;
}
}
}
emp += n - cur;
if (flag) printf("0\n");
else printf("%I64d\n", poww(26, emp));
return 0;
}
后记
不知道为什么一直