bzoj3670[Noi2014]动物园

本文详细解析了bzoj3670[Noi2014]动物园题目,通过求解字符串S的前缀和后缀匹配问题,使用fail函数和递推算法,最终求得所有num[i]+1的乘积模1000000007。代码实现清晰,适合算法学习者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bzoj3670[Noi2014]动物园

题意:

对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。给出字符串S求所有num[i]+1的乘积模1000000007。字符串长度≤1000000

题解:

先求一遍fail函数,得到数组记为next1,然后再求next2数组,表示满足next1[j]*2≤i的next1[j],这一过程也是可以递推的。同时用cnt数组记录next1[j]有多少个。num[i]就是cnt[next2[i]]。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 1000100
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define mod 1000000007
 7 using namespace std;
 8 
 9 char s[maxn]; int next1[maxn],next2[maxn],cnt[maxn],t,len; long long ans;
10 int main(){
11     scanf("%d",&t);
12     while(t--){
13         scanf("%s",s+1); len=strlen(s+1); next1[1]=0; cnt[1]=1; next2[1]=0;
14         inc(i,2,len){
15             int j=next1[i-1]; while(j&&s[j+1]!=s[i])j=next1[j];
16             if(s[j+1]==s[i])next1[i]=j+1,cnt[i]=cnt[next1[i]]+1;else next1[i]=0,cnt[i]=1;
17         }
18         inc(i,2,len){
19             int j=next2[i-1]; if(j*2+2>i)j=next1[j]; while(j&&s[j+1]!=s[i])j=next1[j];
20             if(s[j+1]==s[i])next2[i]=j+1;else next2[i]=0;
21         }
22         ans=1; inc(i,1,len)ans=ans*(cnt[next2[i]]+1)%mod; printf("%lld\n",ans);
23     }
24     return 0;
25 }

 

20160806

转载于:https://www.cnblogs.com/YuanZiming/p/5808565.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值