P2375 [NOI2014] 动物园

P2375 [NOI2014] 动物园

题意是对于每个前缀,求前缀后缀不交的且前后缀相等的前后缀数量数组,1len1061\le len \le 10^6

考虑先求出正常的 nextnext 数组,KMP O(len)O(len) 求解。

对于 nextnext' 数组,可以由前一个数的 nextnext' 数组转移,如果新数大小超过了 i2\frac{i}{2} 就跳到前一个 nextnext 数组。因为如果现在已经超出长度限制,加 11 后一定超出,所以这么做是正确的。

记录 numnum 只需要在过程中递推一下就好了。详见代码。

时间复杂度 O(len)O(len)

#include<bits/stdc++.h>
// #define LOCAL
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
using namespace std;
typedef long long ll;
const int N = 1e6 + 7, mod = 1e9 + 7;
ll ans;
int n,l;
char c[N];
int nex[N],num[N];
void getans () {
num[1] = 1;
int j = 0;
rep(i, 1, l - 1) {
while(j && c[i] != c[j]) j = nex[j];
if(c[i] == c[j]) j++;
nex[i + 1] = j; num[i + 1] = num[j] + 1;
}
j = 0;
rep(i, 1, l - 1) {
while(j && (c[i] != c[j])) j = nex[j];
if(c[i] == c[j]) j++;
while((j<<1) > (i + 1) ) j = nex[j];
ans = ans * (num[j] + 1) % mod;
}
}
int main () {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("my.out", "w", stdout);
#endif
sf("%d" , &n );
while (n--) {
memset(nex, 0, sizeof(nex));
memset(num, 0, sizeof(num));
ans = 1;
sf("%s", c);
l = strlen(c);
getans();
pf("%lld\n", ans);
}
}
posted @   wing_heart  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示