[BZOJ]4650: [Noi2016]优秀的拆分
Time Limit: 30 Sec Memory Limit: 512 MB
Description
Input
Output
输出 TT 行,每行包含一个整数,表示字符串 SS 所有子串的所有拆分中,总共有多少个是优秀的拆分。
Sample Input
aabbbb
cccccc
aabaabaabaa
bbaabaababaaba
Sample Output
5
4
7
我们用 S[i,j]S[i,j] 表示字符串 SS 第 ii 个字符到第 jj 个字符的子串(从 11 开始计数)。第一组数据中,共有 33 个子串存在优秀的拆分:S[1,4]=aabbS[1,4]=aabb,优秀的拆分为 A=aA=a,B=bB=b;S[3,6]=bbbbS[3,6]=bbbb,优秀的拆分为 A=bA=b,B=bB=b;S[1,6]=aabbbbS[1,6]=aabbbb,优秀的拆分为 A=aA=a,B=bbB=bb。而剩下的子串不存在优秀的拆分,所以第一组数据的答案是 33。第二组数据中,有两类,总共 44 个子串存在优秀的拆分:对于子串 S[1,4]=S[2,5]=S[3,6]=ccccS[1,4]=S[2,5]=S[3,6]=cccc,它们优秀的拆分相同,均为 A=cA=c,B=cB=c,但由于这些子串位置不同,因此要计算 33 次;对于子串 S[1,6]=ccccccS[1,6]=cccccc,它优秀的拆分有 22 种:A=cA=c,B=ccB=cc 和 A=ccA=cc,B=cB=c,它们是相同子串的不同拆分,也都要计入答案。所以第二组数据的答案是 3+2=53+2=5。第三组数据中,S[1,8]S[1,8] 和 S[4,11]S[4,11] 各有 22 种优秀的拆分,其中 S[1,8]S[1,8] 是问题描述中的例子,所以答案是 2+2=42+2=4。第四组数据中,S[1,4]S[1,4],S[6,11]S[6,11],S[7,12]S[7,12],S[2,11]S[2,11],S[1,8]S[1,8] 各有 11 种优秀的拆分,S[3,14]S[3,14] 有 22 种优秀的拆分,所以答案是 5+2=75+2=7。
Solution
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MN 60000
#define K 16
#define ms(a) memset(a,0,sizeof(a))
char s[MN+];
int v[MN+],A[MN*+],*sa=A,*rk=sa+MN+,*nsa=rk+MN+,*nrk=nsa+MN+;
int len,h[K][MN+],lg[MN+],L[MN+],R[MN+];
int query(int l,int r)
{
int x=lg[r-l+];
return min(h[x][l],h[x][r-(<<x)+]);
}
int lcp(int x,int y)
{
if(rk[x]>rk[y])swap(x,y);
return query(rk[x]+,rk[y]);
}
int lcs(int x,int y)
{
return lcp(*len+-x,*len+-y);
}
int main()
{
int T,n,i,j,l;long long ans;
for(i=;i<=MN;++i)lg[i]=lg[i+>>]+;
scanf("%d",&T);
while(T--)
{
ms(s);ms(v);ms(A);ms(L);ms(R);
scanf("%s",s+);len=strlen(s+);
s[len+]='a'-;n=len*+;
for(i=;i<=len;++i)s[i+len+]=s[len-i+];
for(i=;i<=n;++i)++v[s[i]];
for(i='a';i<='z';++i)v[i]+=v[i-];
for(i=;i<=n;++i)sa[v[s[i]]--]=i;
for(i=;i<=n;++i)rk[sa[i]]=rk[sa[i-]]+(s[sa[i]]!=s[sa[i-]]);
for(l=;l<n;l<<=,swap(sa,nsa),swap(rk,nrk))
{
for(i=;i<=n;++i)v[rk[sa[i]]]=i;
for(i=n;i;--i)if(sa[i]>l)nsa[v[rk[sa[i]-l]]--]=sa[i]-l;
for(i=;i<l;++i)nsa[v[rk[n-i]]--]=n-i;
for(i=;i<=n;++i)nrk[nsa[i]]=nrk[nsa[i-]]+(rk[nsa[i]]!=rk[nsa[i-]]||rk[nsa[i]+l]!=rk[nsa[i-]+l]);
}
for(i=,l=;i<=n;++i,l?--l:)
if(rk[i]>){for(j=sa[rk[i]-];s[i+l]==s[j+l];++l);h[][rk[i]]=l;}
for(i=;i<K;++i)for(j=;j+(<<i)-<=n;++j)h[i][j]=min(h[i-][j],h[i-][j+(<<i-)]);
for(i=;*i<len;++i)for(j=;j+i<=len;j+=i)
{
int a=min(lcs(j,j+i),i),b=min(lcp(j,j+i),i);
if(a+b>i)++L[j-a+],--L[j+b-i+],++R[j+i-a+i],--R[j+i+b];
}
for(ans=,i=;i<len;++i)ans+=1LL*(R[i]+=R[i-])*(L[i+]+=L[i]);
printf("%lld\n",ans);
}
}
[BZOJ]4650: [Noi2016]优秀的拆分的更多相关文章
- 【刷题】BZOJ 4650 [Noi2016]优秀的拆分
Description 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 AA 和 BB 是任意非空字符串,则我们称该字符串的这种拆分是优秀的.例如,对于字符串 aabaabaa,如果令 A ...
- BZOJ.4650.[NOI2016]优秀的拆分(后缀数组 思路)
BZOJ 洛谷 令\(st[i]\)表示以\(i\)为开头有多少个\(AA\)这样的子串,\(ed[i]\)表示以\(i\)结尾有多少个\(AA\)这样的子串.那么\(Ans=\sum_{i=1}^{ ...
- BZOJ 4650 [Noi2016]优秀的拆分:后缀数组
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4650 题意: 给你一个字符串s,问你s及其子串中,将它们拆分成"AABB&quo ...
- BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组
我们只需要统计在某一个点开始的形如$AA$字符串个数,和结束的个数相乘求和. 首先枚举循环节的长度L.即$\mid (A) \mid=L$ 然后肯定会经过s[i]和[i+L]至少两个点. 然后我们可以 ...
- [NOI2016]优秀的拆分&&BZOJ2119股市的预测
[NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...
- 【BZOJ4560】[NOI2016]优秀的拆分
[BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...
- luogu1117 [NOI2016]优秀的拆分
luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...
- [UOJ#219][BZOJ4650][Noi2016]优秀的拆分
[UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...
- [NOI2016]优秀的拆分(SA数组)
[NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...
随机推荐
- Beta冲刺 第一天
Beta冲刺 第一天 1. 昨天的困难 由于今天还是第一天,所以暂时没有昨天的困难. 2. 今天解决的进度 潘伟靖: 对代码进行了review 1.将某些硬编码改为软编码 2.合并了一些方法,简化代码 ...
- python 面向对象设计思想发展史
这篇主要说的是程序设计思想发展历史,分为概述和详细发展历史 一,概述 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的 指令和数 据.简单来 ...
- JAVA_SE基础——4.path的临时配置&Classpath的配置
这次,我来写下关于path的临时配置的心的 我来说个有可能的实例:如果你去到别人的电脑 又想写代码 又不想改乱别人的path配置的话 再说别人愿意你在别人的电脑上瞎配吗? 那该怎么办呢? 那没问题 ...
- JAVA_SE基础——2.环境变量的配置&测试JDK
哈喽,利用晚上的空余时间再写篇心的~~~ 谢谢大家 前一篇文章 JAVA_SE基础--JDK&JRE下载及安装http://blog.csdn.net/thescript_j/article ...
- python time、datetime、random、os、sys模块
一.模块1.定义模块:用来从逻辑上组织Python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test)包:用来从逻辑上组织 ...
- C语言Linix服务器网络爬虫项目(一)项目初衷和网络爬虫概述
一.项目初衷和爬虫概述 1.项目初衷 本人的大学毕设就是linux上用c写的一个爬虫,现在我想把它完善起来,让他像一个企业级别的项目.为了重复发明轮子来学习轮子的原理,我们不使用第三方框架(这里是说的 ...
- Linux知识积累(2)dirname的使用方法
linux中的cd "$(dirname "$0")"/是什么意思呢? 分析如下: 1.$0 表示当前动行的命令名,一般用于shell 脚本中 2.dirnam ...
- 新概念英语(1-53)An interesting climate
新概念英语(1-53)An interesting climate What's the favourite subject of conversation in England? A:Where ...
- python开发:python字符串操作方法
name = "my \tname is {name} and i am {year} old" capitalize:第一个单词的首字母大写的方法 print(name.capi ...
- java集合 源码解析 学习手册
学习路线: http://www.cnblogs.com/skywang12345/ 总结 1 总体框架 2 Collection架构 3 ArrayList详细介绍(源码解析)和使用示例 4 fai ...