3670: [Noi2014]动物园
题目链接
时间限制: 10 Sec 内存限制: 512 MB
提交: 3558 解决: 1925
[提交][][]
题目描述
近日,园长发现动物园中好吃懒做的动物越来越多了。例如企鹅,只会卖萌向游客要吃的。为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法。

某天,园长给动物们讲解KMP算法。

园长:“对于一个字符串S,它的长度为L。我们可以在O(L)的时间内,求出一个名为next的数组。有谁预习了next数组的含义吗?”

熊猫:“对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度记作next[i]。”

园长:“非常好!那你能举个例子吗?”

熊猫:“例S为abcababc,则next[5]=2。因为S的前5个字符为abcab,ab既是它的后缀又是它的前缀,并且找不到一个更长的字符串满足这个性质。同理,还可得出next[1] = next[2] = next[3] = 0,next[4] = next[6] = 1,next[7] = 2,next[8] = 3。”

园长表扬了认真预习的熊猫同学。随后,他详细讲解了如何在O(L)的时间内求出next数组。

下课前,园长提出了一个问题:“KMP算法只能求出next数组。我现在希望求出一个更强大num数组一一对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。例如S为aaaaa,则num[4] = 2。这是因为S的前4个字符为aaaa,其中a和aa都满足性质‘既是后缀又是前缀’,同时保证这个后缀与这个前缀不重叠。而aaa虽然满足性质‘既是后缀又是前缀’,但遗憾的是这个后缀与这个前缀重叠了,所以不能计算在内。同理,num[1] = 0,num[2] = num[3] = 1,num[5] = 2。”

最后,园长给出了奖励条件,第一个做对的同学奖励巧克力一盒。听了这句话,睡了一节课的企鹅立刻就醒过来了!但企鹅并不会做这道题,于是向参观动物园的你寻求帮助。你能否帮助企鹅写一个程序求出num数组呢?

特别地,为了避免大量的输出,你不需要输出num[i]分别是多少,你只需要输出对1,000,000,007取模的结果即可。

输入
第1行仅包含一个正整数n ,表示测试数据的组数。随后n行,每行描述一组测试数据。每组测试数据仅含有一个字符串S,S的定义详见题目描述。数据保证S 中仅含小写字母。输入文件中不会包含多余的空行,行末不会存在多余的空格。

输出
包含 n 行,每行描述一组测试数据的答案,答案的顺序应与输入数据的顺序保持一致。对于每组测试数据,仅需要输出一个整数,表示这组测试数据的答案对 1,000,000,007 取模的结果。输出文件中不应包含多余的空行。

样例输入
3
aaaaa
ab
abcababc

样例输出
36
1
32

提示
n≤5,L≤1,000,000

来源

题解
说实话题意有点不理解,为什么网上的标程对于长度为 1 的字符串会输出 1?

其实这和hdu-3336 Count the string这题很像。自己居然还是写不下来……

首先我们发现,某一段字符串中又是前缀又是后缀的最长子段就是 p[j]~j (假设这段字符串是原串的1~j)。
实际上还可能有更短的又是前缀又是后缀的子段,如何找到这种子段呢?
不容置疑,这种子段若存在于1~j 这段,那么也一定存在于1 ~ j - p[j] 这段。

详解,懂了就跳过。因为这段与 p[j]~j 这段相等,而若更短子段存在,那么这个子段必定是 p[j]~j 这段的某个子段。

所以我们每次都可以递归求出所有的子段,但是我们发现每次递归都是不断往前的,所以可以记忆化(也就是DP),f[i] 表示以 i 为结尾的前缀中,存在的既是前缀又是后缀的字符串数量(包括自身)。对于每个 i,p[i](也等于当前的 j)就是最长的前缀又是后缀的字符串,所以 f[i] = f[p[i]] + 1 = f[j] + 1。

然而我们似乎忘记了一件事情,就是长度不能过半。那么每次 j 都往回推,推到一定的位置,再把这个当前的 f[j] 累计给 ans。
可是这不就退化成 N^2 的复杂度了吗?其实不然,因为我们的 j 一旦从 j1 往回推了以后到了 j2,那么接下来我们不用把 j 恢复到 j1 的位置,只需要从 j2 的位置继续就好了。

详解,懂了就跳过。因为那个往前递归的过程基本是相同的,重复的,比如 p={0,1,2,3,4,5}(其中字符串第 1 位下标为 1),那么第 4、5 位递归到第 2 位的过程如下:{4->3->2} {5->4->3->2}。所以我们是否只许在上一次的基础上,看看是否要继续往后。
如果还不理解,我们可以对上面的结论进行分类讨论。
如果 i 这位失陪了,p[i] = 0,那么不用说,f[i] = 1。注意:上一位没有失陪。那么 i-1 肯定处于一个循环节(所有可能循环节中最短的循环节)上(可能不是完整的循环节,比如 abcab 中的后缀 “ab”),那么,往回跳了,肯定还在一个相同的循环节上(若干个循环节,第一段的 p[i] 肯定都是 0,否则这就不是最短的循环节,而 j 是不可能跳过 0 的),既然是相同的循环节,那么不影响结果。
如果 i 这位没失陪,根据上述,肯定在一个循环节上(不一定完整),那么不影响。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+5,MOD=1000000007;
int T,n,p[maxn],f[maxn];
char s[maxn];
long long F()
{long long ans=1;memset(s,0,sizeof s);memset(f,0,sizeof f);scanf("%s",s+1);n=strlen(s+1);if (n<=1) return 0;int j=p[1]=0;f[1]=1;for (int i=2;i<=n;i++){while (j>0&&s[i]!=s[j+1]) j=p[j];p[i]=j+=s[i]==s[j+1];f[i]=f[j]+1;}j=0;for (int i=2;i<=n;i++){while (j>0&&s[i]!=s[j+1]) j=p[j];j+=s[i]==s[j+1];while (j>i/2) j=p[j];ans=ans*(f[j]+1)%MOD;}return ans;
}
int main()
{scanf("%d",&T);while (T--) printf("%lld\n",F());return 0;
} 

bzoj-3670 [Noi2014]动物园相关推荐

  1. bzoj 3670 [NOI2014]动物园

    3670: [Noi2014]动物园 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 2032  Solved: 1077 [Submit][Stat ...

  2. bzoj 3670: [Noi2014]动物园 kmp与扩展kmp

    bzoj 3670: [Noi2014]动物园容 Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才 ...

  3. bzoj 3670: [Noi2014]动物园

    Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1407  Solved: 749 [Submit][Status][Discuss] Descrip ...

  4. [BZOJ]3670 [NOI]2014 动物园 KMP好题

    3670: [Noi2014]动物园 Time Limit: 10 Sec   Memory Limit: 512 MB Submit: 3045   Solved: 1646 [ Submit][ ...

  5. BZOJ3670 [Noi2014]动物园 【KMP计数】

    3670: [Noi2014]动物园 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 3143  Solved: 1690 [Submit][Stat ...

  6. P2375 [NOI2014] 动物园 kmp fail指针/倍增

    传送门 文章目录 题意: 思路: 题意: 思路: 由kmpkmpkmp中失配数组nenene的含义我们知道,ne[i],ne[ne[i]],...ne[i],ne[ne[i]],...ne[i],ne ...

  7. bzoj3670 [Noi2014]动物园

    [Noi2014]动物园 Time Limit: 10 Sec Memory Limit: 512 MB Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游 ...

  8. 洛谷P2375 [NOI2014] 动物园 题解

    洛谷P2375 [NOI2014] 动物园 题解 题目链接:P2375 [NOI2014] 动物园 题意: 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物 ...

  9. BZOJ 3668: [Noi2014]起床困难综合症( 贪心 )

    之前以为xor,or,and满足结合律...然后连样例都过不了 早上上体育课的时候突然想出来了...直接处理每一位是1,0的最后结果, 然后从高位到低位贪心就可以了... 滚去吃饭了.. ------ ...

最新文章

  1. mysql操作数字名称的schema时字符的逃逸问题
  2. 刚获20亿投资的通用无人车Cruise估值达300亿美元,叫板Waymo!
  3. 密码篇——对称加密—DES
  4. mysql 定时同步数据_MySQL数据同步之otter
  5. Microsoft Team Foundation Server 2010安装指南
  6. 计算机学院五名学生开发手语app,大学生团队研发成功“聋人自然手语翻译器”APP...
  7. java引擎组件_Java 脚本引擎入门
  8. 蛋白粉有什么作用?搭配这些食物帮助提升免疫力!
  9. python语法_算数运算+赋值运算符+比较运算符+逻辑运算符
  10. 5G NR协议栈----总体架构
  11. 欧姆定律基本知识(笔记)
  12. Linux下实现一个网卡绑定多个IP地址
  13. mysql学习一 常用语句
  14. 金蝶盘点机PDA轻松扫码生产领料,生产型企业进销存条码管理软件
  15. 局域网体系结构与IEEE标准
  16. windows server 2008 R2 怎么集成USB3.0驱动
  17. QT6程序全屏和隐藏鼠标指针笔记
  18. 内外兼修 华润啤酒的“有为”哲学
  19. 基于Yolov5的草莓病虫害检测识别
  20. 基于改进的蚂蚁群算法求解最短路径问题、二次分配问题、背包问题【MatlabPython代码实现】

热门文章

  1. Java技术开发实战分享
  2. 02回声服务端与客户端(瑕疵版)
  3. 手机读取大容量存储卡导致手机反应速度变慢
  4. TIMESTAMPDIFF与TIMESTAMPADD
  5. 算法导论主定理证明(3)
  6. 电子纸张模块的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  7. 51单片机DS18B20+DS1302+LCD12864实时显示时间日期温度
  8. 井字棋版本1.0(对抗人工智障)
  9. CDN加速究竟是怎么加速的 其工作原理是怎样的
  10. 不懂开发,也可以开发酷炫的可视化大屏