luogu P2375 [NOI2014]动物园
大意
就是定义一个类似
K
M
P
KMP
KMP中的
n
x
t
nxt
nxt 数组的东西
n
u
m
num
num,不过
n
u
m
i
num_i
numi表示前缀
s
t
[
1...
i
]
st[1...i]
st[1...i] 能匹配的前缀的数量且匹配的前缀的长度不能超过
i
/
2
i/2
i/2
学过AC自动机的都知道这很简单,如果不考虑长度限制,个数就直接在构造
n
x
t
nxt
nxt数组的时候继承一下
n
u
m
num
num就行了
即
n
u
m
[
i
]
=
n
u
m
[
n
x
t
[
i
]
]
+
1
num[i] = num[nxt[i]] + 1
num[i]=num[nxt[i]]+1
就这样,如果匹配的时候长度不合法就往前跳,然后直接跑一遍就完事了
code:
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 2000005
using namespace std;
int t, n, nxt[N], ha[N];
char st[N];
int main(){
scanf("%d", &t);
while(t --){
memset(nxt, 0, sizeof nxt);
memset(ha, 0, sizeof ha);
scanf("%s", st + 1);
int n = strlen(st + 1);
int j = 0;ha[1] = 1;
for(int i = 1; i < n; i ++){
while(j && st[j + 1] != st[i + 1]) j = nxt[j];
if(st[j + 1] == st[i + 1]) j ++;
nxt[i + 1] = j, ha[i + 1] = ha[j] + 1;//构造nxt和num(ha)
}
j = 0;
long long ans = 1;
for(int i = 0; i <= n; i ++){
while(j && st[j + 1] != st[i + 1]) j = nxt[j];//正常的跳
if(st[j + 1] == st[i + 1]) j ++;//匹配一波
while(j * 2 > i + 1) j = nxt[j];//如果长度不合法就继续往前跳,注意这里是求i+1位的
ans = ans * (ha[j] + 1) % 1000000007;//记得mo一蛤
}
printf("%lld\n", ans);
}
return 0;
}
总结
NOI竟然考这种水题
这应该算是签到题吧,只要冷静分析还是做得出来的
嗯