[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)\) ...
随机推荐
- 2017.12.13 Java中是怎样通过类名,创建一个这个类的数组
先在类方法中定义数组的方法: public int[] method6(int[] arr){ for(int i = 0; i<arr.length;i++){ arr[i] = (int)( ...
- 安装CentOS6.9虚拟机
安装CentOS6.9 之前在学习项目时,都是用的按键好的虚拟机.这次自己也尝试搭建一下.(虽然也是google的) 首先大部分过程都是参考https://blog.csdn.net/pengpeng ...
- python生成随机数
import random rnd=rand.uniform(0,10)
- display:inline-block解决文字有间隙问题
定义:display:inline-block是使元素以块级元素的形式呈现在行内.意思就是说,让这个元素显示在同一行不换行,但是又可以控制高度和宽度,这相当于内联元素的增强. 但是display:in ...
- node第一天
一.主要执行的文件命名一般为main.js var aModule =require('./a.js');//相对路径 var aModule =require('a.js');//专门从node_m ...
- linux内核--定时器API
/**<linux/timer.h> 定时器结构体 struct timer_list { ........ unsigned long expires; --内核希望定时器执行的jiff ...
- git bash学习3 -简单杂乱知识点记录
branch 新建分支 git init git add git commit 先新建一个仓库以及master 然后新建分支 git branch BranchName 然后切换分支 git chec ...
- 自动化运维工具——ansible模板与roles(四)
一. 模板Templates 文本文件,嵌套有脚本(使用模板编程语言编写) Jinja2语言,使用字面量,有下面形式 字符串:使用单引号或双引号 数字:整数,浮点数 列表:[item1, item2, ...
- JavaScript日期加减
JS中的日期加减使用以下方式: varcurrentDate = new Date(); 对日期加减: date.setDate(date.getDate()+n); 对月加减: date.setMo ...
- java util - Unicode转换工具
测试代码 package cn.java.codec.unicode; public class Test { public static void main(String[] args) throw ...