[NOI 2014] 动物园:KMP算法,递推

又看错题了……这个毛病不改不行啊。所幸没差太远。以后写题解我决定加上“题意简述”。

题意:给一个字符串s,长度L不超过1百万,记所有既是子串s[0..i]的前缀,又是其后缀,且该前缀、后缀不重叠的字符串的数量为num[i],求num[0], num[1], …, num[L-1]之积对某个给定大质数取模的结果。多组数据。

题面中给了背景:KMP算法。于是我把“数量”当成了“最大长度”。

在《NOI导刊》的培训班听老师讲过,但是没搞清楚……又拿出来想了想。

如果不考虑“前缀、后缀不重叠”,并且不等于整个子串,怎么求这样的字符串的数量?跑KMP的时候递推一个数组cnt,表示沿next数组从i跳转有多少次成功匹配,即为所求。因为每跳转一次,相当于找到一个前缀=后缀;cnt[0] = 0。

如果加上这个限制呢?

先跑一遍KMP,求出next和上述cnt。再跑一遍,只是在跳转的条件中加上j*2 >= i,每次停下来之后更新答案。注意,cnt不计s[0..j],所以这里要+1。

抛开这道题,把next[i]定义为真前缀等于后缀的最大长度有点别扭……跳出while循环后,j=0既可能代表成功匹配到s[0],也可能代表没有匹配。把next[i]定义为在i处失配后下一个比较的位置,并且置next[0] = -1可能会好一些。

#include <cstdio></
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值