$luogu2375[NOI2014]$
\(problem\)
其中,\(next[i],next[next[i]],next[next[next[i]]]......\)都是这个前缀串i的公共前后缀,而且只有它们是公共前后缀
那么,我们其实只要在求\(next\)的过程中,顺便把这个公共前后缀的数量递推一下,就得到了一个弱化版的\(num数组\):可以重叠的公共前后缀数量,我们称之为\(ans\) 如何去除有重叠的?
还是看上面那张图
首先next数组有一个性质:\(next[i] < inext[i]<i\)
也就是说,一旦有一个递归了\(n\)层的\(next\),比原前缀i的长度的一半要小,那么这个\(next\)的递推出的答案\(ans\)就是\(i\)的\(num\)了
一个问题
假如我们拿到的串是\(1e6个'a'\),那么上面那个算法就会被卡成O(\(n^2\))道理的话大家可以想一想(每一次递归都只会把\(next[i]\)变小1)
那么我们需要做一个优化,来解决这个问题,而解决问题的核心就是:\(减少重复递归\)
减少重复递归......\(有没有想到什么?\)
没错,就是如同求\(next\)时一样的方法!
我们将递归用的变量\(j\)的值不更新,这样,求完了i的答案以后,\(j\)的位置一定在\(i/2\)的左边,也就是它已经满足要求了
这时再递归求解,总时间效率是\(O(n)\)的
#include <bits/stdc++.h>
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++) {
while(j&&(a[i]!=a[j])) j=fail[j];
j+=(a[i]==a[j]);
fail[i+1]=j;
ans[i+1]=ans[j]+1;
}
j=0;
cnt=1;
for(i=1; i<n; i++) {
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;
}
printf("%lld\n",cnt);
}
return 0 ;
}
随机推荐
- Linux之iptables(五、firewall命令及配置)
firewalld服务 firewalld是CentOS 7.0新推出的管理netfilter的工具 firewalld是配置和监控防火墙规则的系统守护进程.可以实现iptables,ip6table ...
- pandas 处理 excel
先写下来,以免后续忘记,有很多都是之前用过的, 依旧忘!!! 嘤嘤嘤 data_file = pandas.read_excel('/imporExcel/2017_7_7.xlsx',sep = ' ...
- 如何使用loadrunner进行web网站性能测试
loadrunner压力测试原理 本质就是在loadrunner上模拟多个用户同时按固定行为访问web站点.其中固定行为在loadrunner中是通过录制脚本定义的,多个用户同时访问的策略是在load ...
- Go语言语法说明
Go语言语法说明 go语言中的go func(){}() 表示以并发的方式调用匿名函数func 深入讲解Go语言中函数new与make的使用和区别 前言 本文主要给大家介绍了Go语言中函数new与ma ...
- CF578D. LCS Again
n<=100000个字符的小写字母串,问用前m<=26个小写字母能拼出多少个和原串lcs=n-1的字符串. 首先把字符串划分成若干个连续相同的段,如aaa|bb|c|dd,然后题目即要求从 ...
- HBase连接数据库(集群)
一.使用java接口对hbase进行表的创建1.引入需要的jar包2.代码: public static void main(String[] args) throws Exception { //得 ...
- Java发送带附件的QQ邮箱
由于腾讯公司给QQ邮箱增加了一个授权码的密码保护,导致之前网上很多代码都不能用,于是就自己敲了一份demo. 注意在密码那里可能需要授权码,具体设置:http://service.mail.qq.co ...
- MySQL慢日志切割邮件发送脚本
#!/bin/bashtime=`date -d yesterday +"%Y-%m-%d"`slowlog='/usr/local/percona/data/slow.log'# ...
- Ubuntu 16.04安装uGet替代迅雷,并在Chrome中设置为默认下载器
uGet是采用aria2作为下载后端,所以两个软件都必须同时安装. 1.安装uGet sudo add-apt-repository ppa:plushuang-tw/uget-stable sudo ...
- C#中类的详解
类定义的具体语法形式类的访问修饰符 修饰符 类名{ 类的成员} 类的访问修饰符:用于设定对类的访问权限,包括public.internal或者不写,用internal或者不写时代表只能在当前项目中访问 ...