bzoj 4650(洛谷 1117) [Noi2016]优秀的拆分——枚举长度的关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4650
https://www.luogu.org/problemnew/show/P1117
和 bzoj2119 股市的预测 一样。
考虑算出每个点往前的 AA 的个数和往后的 BB 的个数,每个点作为 AA 和 BB 分界点的答案累加起来就行。
算一个点开始的 AA 的个数,就是枚举 A 的长度 L ,然后每 L 个分为一段,在段的开头求 LCP 和 LCS ,给合法的位置区间加1就行。
一开始写成 n2 了,还能有 95 分。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int Mn(int a,int b){return a<b?a:b;}
int Mx(int a,int b){return a>b?a:b;}
const int N=6e4+,K=;
int T,n,len,sa[N],rk[N],tp[N],tx[N],ht[N][K],lg[N],bin[K];
int s[N],f[N],g[N]; char ch[N];
void Rsort(int n,int nm)
{
for(int i=;i<=nm;i++)tx[i]=;
for(int i=;i<=n;i++)tx[rk[i]]++;
for(int i=;i<=nm;i++)tx[i]+=tx[i-];
for(int i=n;i;i--)sa[tx[rk[tp[i]]]--]=tp[i];
}
void get_sa(int n)
{
int nm=;
for(int i=;i<=n;i++)tp[i]=i,rk[i]=s[i]+;
Rsort(n,nm);
for(int k=;;k<<=)
{
int tot=;
for(int i=n-k+;i<=n;i++)tp[++tot]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++tot]=sa[i]-k;
Rsort(n,nm);memcpy(tp,rk,sizeof rk);
nm=; rk[sa[]]=;
for(int i=;i<=n;i++)
{
int u=sa[i]+k,v=sa[i-]+k; if(u>n)u=;if(v>n)v=;
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[u]==tp[v])?nm:++nm;
}
if(nm==n)break;
}
}
void ht_init(int n)
{
for(int i=;i<=n;i++)lg[i]=lg[i>>]+;
bin[]=;for(int i=;i<=lg[n];i++)bin[i]=bin[i-]<<;
}
void get_ht(int n)
{
for(int i=,k=,j;i<=n;i++)
{
for((k?k--:),j=sa[rk[i]-];i+k<=n&&j+k<=n&&s[i+k]==s[j+k];k++);
ht[rk[i]][]=k;
}
for(int t=;t<=lg[n];t++)
for(int i=;i+bin[t]-<=n;i++)
ht[i][t]=Mn(ht[i][t-],ht[i+bin[t-]][t-]);
}
int qry_ht(int l,int r,bool fx)
{
if(l==r)return fx?sa[l]-n-:n-sa[l]+;
if(l>r)swap(l,r); int d=lg[r-l];
return Mn(ht[l+][d],ht[r-bin[d]+][d]);
}
void add(int x,int k,int *f){for(;x<=len;x+=(x&-x))f[x]+=k;}
int qry(int x,int *f){int ret=;for(;x;x-=(x&-x))ret+=f[x];return ret;}
int main()
{
scanf("%d",&T); ht_init(); s[]=;
while(T--)
{
scanf("%s",ch+);
n=strlen(ch+); len=n*+;
for(int i=,j=len;i<=n;i++,j--)s[i]=s[j]=ch[i]-'a'+;
s[n+]=; get_sa(len); get_ht(len); memset(f,,sizeof f); memset(g,,sizeof g);
for(int L=,lm=n>>,lst=,tmp=L<<;L<=lm;L++,lst=,tmp+=)
for(int i=;i+L<=n;i+=L)
{
int l2=qry_ht(rk[i],rk[i+L],);
int l1=qry_ht(rk[len-i+],rk[len-i-L+],);
int st=Mx(lst+,i-l1+);
int en=i+l2-L;
if(en<st)continue; lst=en;
add(st,,f); add(en+,-,f);
add(st+tmp-,,g); add(en+tmp,-,g);
}
ll ans=;
for(int i=;i<n;i++)
ans+=(ll)qry(i,g)*qry(i+,f);
printf("%lld\n",ans);
}
return ;
}
bzoj 4650(洛谷 1117) [Noi2016]优秀的拆分——枚举长度的关键点+后缀数组的更多相关文章
- 【洛谷1117_BZOJ4650】[NOI2016] 优秀的拆分(哈希_后缀数组_RMQ)
题目: 洛谷1117 分析: 定义把我校某兔姓神犇Tzz和他的妹子拆分,为"优秀的拆分" 随便写个哈希就能有\(95\)分的好成绩-- 我的\(95\)分做法比fei较chang奇 ...
- bzoj 2119 股市的预测——枚举长度的关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 就是找差分序列上中间差 m 的相等的两段. 考虑枚举这样一段的长度 L .可以把序列分 ...
- bzoj 4650 & 洛谷 P1117 优秀的拆分 —— 枚举关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 ...
- 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)
真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...
- [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)
[BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...
- 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化
洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...
- 【BZOJ4560】[NOI2016]优秀的拆分
[BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...
- [NOI2016]优秀的拆分&&BZOJ2119股市的预测
[NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...
- luogu1117 [NOI2016]优秀的拆分
luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...
随机推荐
- Linux磁盘管理,vi编辑器以及包管理器
一.Linux磁盘管理 Linux磁盘管理常用的三个命令为df,du,fdisk df:列出文件系统的整体磁盘使用量,利用这个命令来获取磁盘被占用了多少空间,,目前还剩下多少空间用法:df [-ahi ...
- OC BLOCK和协议
一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. block实际上是: 指向结构体的指针 BOLC ...
- C#阿里云移动推送列表
C#阿里云移动推送列表 这个就在上期随笔的基础之上,加一个 函数就行了. 简单的. 附上源码:一下代码只要把参数改一下就可以了,中间几个参数 可以灵活修改 /// <summary> ...
- bzoj3601
题解:gi(pq=pqi-pqi+di 至于为什么,可以看看往上的题解 代码: #include<bits/stdc++.h> using namespace std; typedef l ...
- Schema——demo
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 《Python》 文件操作
一.文件操作基本流程: 1.文件基本操作初识: 打开文件: 文件句柄 = open(‘文件路径’,‘编码方式’,‘打开方式’) 第一种:f = open('d:\'a.txt',encoding='u ...
- 1.1 C++布尔类型(bool)
注意: c++ 中 cout << true << endl; 输出为 1: 布尔类型(bool)是C++新增的一种基本数据类型.在标准的C语言中并未定义bool类型,如果需 ...
- C++primer 练习4.31-4.35
Exercise 4.31: 编写程序从标准输入设备读入字符串,并把该串存放在字 符数组中.描述你的程序如何处理可变长的输入.提供比 你分配的数组长度长的字符串数据测试你的程序. string in_ ...
- MyEclipse WebSphere开发教程:安装和更新WebSphere 6.1, JAX-WS, EJB 3.0(三)
MyEclipse超值折扣 限量 100 套! 立即开抢>> [MyEclipse最新版下载] MyEclipse支持Java EE技术(如JAX-WS和EJB 3.0),它们以功能包的形 ...
- 【重大更新】DevExpress v17.2新版亮点—WinForms篇(二)
用户界面套包DevExpress v17.2终于正式发布,本站将以连载的形式为大家介绍各版本新增内容.开篇介绍了DevExpress WinForms v17.2 Data Grid Control ...