[NOI2014][bzoj3670] 动物园 [kmp+next数组应用]
题面
思路
首先,这题最好的一个地方,在于它给出的关于$next$的讲解实在是妙极......甚至可以说我的kmp是过了这道题以后才脱胎换骨的
然后是正文:
如何求$num$数组?
这道题的输入有1e6个字符,显然需要$O\left(n\right)$左右级别的算法来解
先看到$num$的定义:不互相重叠的公共前后缀个数
这说明什么?
说明$num$不同于$next$记录的是一个最大值,它记录的是一个和值
而这个和值,是可以推出来的
考虑一个前缀$i$的$next[i]$,它长这样:

其中,$next[i]$,$next[next[i]]$,$next[next[next[i]]]$......都是这个前缀串i的公共前后缀,而且只有它们是公共前后缀
那么,我们其实只要在求$next$的过程中,顺便把这个公共前后缀的数量递推一下,就得到了一个弱化版的$num$数组:可以重叠的公共前后缀数量,我们称之为$ans$
如何去除有重叠的?
还是看上面那张图
首先$next$数组有一个性质:$next[i] < i$
也就是说,一旦有一个递归了n层的next,比原前缀i的长度的一半要小,那么这个next的递推出的答案$ans$就是i的$num$了
一个问题
假如我们拿到的串是1e6个'a',那么上面那个算法就会被卡成$O\left(n^2\right)$,道理的话大家可以想一想(每一次递归都只会把next[i]变小1)
那么我们需要做一个优化,来解决这个问题,而解决问题的核心就是:减少重复递归
减少重复递归......有没有想到什么?
没错,就是如同求$next$时一样的方法!
我们将递归用的变量$j$的值不更新,这样,求完了$i$的答案以后,$j$的位置一定在$\frac i2$的左边,也就是它已经满足要求了
这时再递归求解,总时间效率是$O\left(n\right)$的
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll MOD=1e9+7;
int n,fail[1000010],ans[1000010];ll cnt;char a[1000010];
int main(){
int T,i,j;scanf("%d",&T);
while(T--){
scanf("%s",a);n=strlen(a);
memset(fail,0,sizeof(fail));
j=0;ans[0]=0;ans[1]=1;
for(i=1;i<n;i++){//求解next
while(j&&(a[i]!=a[j])) j=fail[j];
j+=(a[i]==a[j]);fail[i+1]=j;ans[i+1]=ans[j]+1;//递推记录ans
}
j=0;cnt=1;
for(i=1;i<n;i++){//求解num
while(j&&(a[i]!=a[j])) j=fail[j];
j+=(a[i]==a[j]);
while((j<<1)>(i+1)) j=fail[j];
cnt=(cnt*(ll)(ans[j]+1))%MOD;//记得+1
}
printf("%lld\n",cnt);
}
}
[NOI2014][bzoj3670] 动物园 [kmp+next数组应用]的更多相关文章
- uoj #5. 【NOI2014】动物园 kmp
#5. [NOI2014]动物园 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/5 Description 近日 ...
- 【BZOJ3670】【NOI2014】动物园 [KMP][倍增]
动物园 Time Limit: 10 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 近日,园长发现动物园中好吃懒做的动物 ...
- BZOJ-3670 动物园 KMP+奇怪的东西
YveH爷再刷KMP,DCrusher看他刷KMP,跟着两个人一块刷KMP... 3670: [Noi2014]动物园 Time Limit: 10 Sec Memory Limit: 512 MB ...
- 【NOI2014】动物园 - KMP
题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天, ...
- LG2375/LOJ2246 「NOI2014」动物园 KMP改造
问题描述 LG2375 LOJ2246 题解 看了题解,需要回看,需要继续通过本题深入理解KMP. 为了将 \(\mathrm{KMP}\) 和只插入了一个模式串的\(\mathrm{AC}\)自动机 ...
- UOJ #5. 【NOI2014】动物园 扩大KMP
第一次NOI称号. ... 扩展假设知道KMP如果. .. . 就是水题了. ... #5. [NOI2014]动物园 统计提交情况 描写叙述 提交 近日.园长发现动物园中好吃懒做的动物越来越多了.比 ...
- uoj #5. 【NOI2014】动物园
#5. [NOI2014]动物园 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的园长决定开设算法班,让 ...
- HDU 1358 Period(KMP next数组运用)
Period Problem Description For each prefix of a given string S with N characters (each character has ...
- 【BZOJ3670】【NOI2014】动物园(KMP算法)
[BZOJ3670]动物园(KMP算法) 题面 BZOJ 题解 神TM阅读理解题 看完题目之后 想暴力: 搞个倍增数组来跳\(next\) 每次暴跳\(next\) 复杂度\(O(Tnlogn)\) ...
随机推荐
- mongodb索引 全文索引之相似度查询
我们在百度搜索中,可以看到与自己搜索度内容越相关度,排在越前面,这个需求可以在mongodb中很简单度实现,mongodb的全文索引不仅可以返回相匹配的查询结果,而且可以告诉你查询结果与你的查询条件多 ...
- Deep Learning 优化方法总结
Stochastic Gradient Descent (SGD) SGD的参数 在使用随机梯度下降(SGD)的学习方法时,一般来说有以下几个可供调节的参数: Learning Rate 学习率 We ...
- Java时间为什么从1970-01-01 00:00:00 000开始
不仅仅是Java,几乎所有的语言的时间都是从这一刻开始算起的. 原因:java起源于UNIX系统,而UNIX认为1970年1月1日0点是时间纪元. 最初计算机操作系统是32位,而时间也是用32位表示. ...
- Smallest Common Multiple-freecodecamp算法题目
Smallest Common Multiple 1.要求 找出能被两个给定参数和它们之间的连续数字整除的最小公倍数. 2.思路 设定一个twoMultiple(a,b)函数,求出输入两个参数的最小公 ...
- ElasticSearch High Level REST API【3】Scroll 滚屏
ES中提供了 FROM/SIZE 分页,但这种分页有性能瓶颈. Scroll会以间隔时间滚屏的方式返回全部的查询数据,可以作为数据量很大的情况下,分页的一个替代方案 完整的示例如下: public v ...
- 进入docker容器并执行命令的的3中方法
进入docker容器并执行命令的的3中方法 docker exec nsenter docker attach "container" 建议使用nsenter, exec有 ...
- Linux监控二之cacti简单安装部署
目录 cacti简单部署 1 环境依赖包部署 1 1. cacti中文版0.8e搭建 2 2. cacti安装向导 url:http://192.168.200.243/ ...
- [Wolfgang Mauerer] 深入linux 内核架构 第十三章 系统调用
作为Linux开发爱好者,从事linux 开发有三年多时间.做过bsp移植,熟悉u-boot代码执行流程:看过几遍<linux 设备驱动程序开发>,分析过kernel启动流程,写过驱动,分 ...
- JZOJ 1266. 玉米田
1266. 玉米田(cowfood.pas/c/cpp) (File IO): input:cowfood.in output:cowfood.out Time Limits: 1000 ms Me ...
- ubuntu下vim的简单配置
该文章只是进行符合自己习惯的最基本的配置,更加高级的配置请参考更加有含量的博文! 1.打开vim下的配置文件 sudo vim /etc/vim/vimrc 2.在这个文件中,会有这么一句:synta ...