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 ...
随机推荐
- 最应该注意的Oracle版本之一
最近以来,两个用户的库接连出现问题,经过查阅资料和分析,确定为数据库bug所致,其实,早在很久前,也遭遇过这个版本的类似bug,当时似乎还惊动了原厂的技术人员,后来确定为这个版本的bug,这个版本就是 ...
- Mac安装zsh oh-my-zsh
我们将安装 zsh ,其拓展功能和主题将由 oh-my-zsh 提供.其中Env.sh 文件用于维护别名(aliases),输出(exports)和路径改变(path changes)等等,以免影响 ...
- Windows系统配置Python环境,python2和python3共存
Windows系统配置python2和python3共存 1.下载python: https://www.python.org/downloads/ 注:选择需要的版本(python2 or ...
- POJ 1860 Bellman-Ford算法
转载链接:http://blog.csdn.net/lyy289065406/article/details/6645778 提示:关键在于反向利用Bellman-Ford算法 题目大意 有多种汇币, ...
- Nodejs之mssql模块的封装
在nodejs中,mssql模块支持sqlserver数据库操作.今天将mssql模块的某些功能封装为一个类,方便以后调用.封装的功能有执行存储过程,执行查询语句操作等.如果本篇文章对大家有帮助,那就 ...
- 使用Setup安装Windows8 RTM方法
1.下载Windows 8 RTM版. 2.解压ISO映像或加载虚拟光驱. 3.为了安装双系统,打开sources文件夹中的setup.exe才可. 4.打开后选择“在线获取安装程序的最新更新(推荐) ...
- 关于rimworld(边缘之地)
低缓的音乐 广阔的原野 丰富而不杂乱的地表 完美的殖民拓荒世界. 各种随机地形,丰富的资源.林木与矿产.随机生成的大世界给人真实世界的感觉. 动态而和谐的画面,随风摇摆的植被,跳跃的兔子,以及 ...
- NBUT 1219 Time 2010辽宁省赛
Time limit 1000 ms Memory limit 131072 kB Digital clock use 4 digits to express time, each digit ...
- 第十五篇 make中的隐式规则概述
前面我们讲到了makefile的依赖拆分的知识,现在可以引申出这样一个问题,如果同一个目标的不同命令拆分的写到不同地方会发生什么?下面我们给出程序和执行结果: 可见后面的命令会覆盖前面的命令, ...
- iOS-----推送机制(下)
推 送 机 制(下) 单击”从证书颁发机构请求证书”后,将会显示下图所示的对话框 输入电子邮件地址和常用名称,并选中“存储到磁盘”单选钮,然后单击“继续”按钮,该程序将会创建一个“Certificat ...