bzoj 4650 & 洛谷 P1117 优秀的拆分 —— 枚举关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4650
https://www.luogu.org/problemnew/show/P1117
枚举每一段 a 的长度,然后分块,后缀数组求出每一块首关键点附近的可行范围;
然后用线段树区间加,区间查询;
在开头范围查询结尾,就得到长度 <= 当前长度 d 的前半部分接上长度 = d 的后半部分的答案;
在结尾范围查询开头,就得到长度 = d 的前半部分接上长度 < d 的后半部分的答案,正好组合了所有情况!
于是写了,跑出来发现比别人慢了很多;
然后发现为什么要边找边算答案...可以差分数组区间加,最后直接每个位置算答案即可...
注意多组数据,要清空 rk[n+1] 和 tp[n+1],因为求后缀数组的时候用到了超出 n 的 tp(rk) 。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs ((x<<1)|1)
using namespace std;
typedef long long ll;
int const xn=6e4+;//n<<1
int rk[xn],sa[xn],tax[xn],tp[xn],ht[xn][],bin[],bit[xn],op[xn];
ll sum[][xn<<],lzy[][xn<<];//n<<2
char s[xn];
int Min(int x,int y){return x<y?x:y;}
int Max(int x,int y){return x>y?x:y;}
void rsort(int n,int m)
{
for(int i=;i<=m;i++)tax[i]=;
for(int i=;i<=n;i++)tax[rk[tp[i]]]++;
for(int i=;i<=m;i++)tax[i]+=tax[i-];
for(int i=n;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];
}
void work(int n)
{
int m=; for(int i=;i<=n;i++)rk[i]=s[i],tp[i]=i;
rk[n+]=; tp[n+]=;//!
rsort(n,m);
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;i++)tp[++num]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++num]=sa[i]-k;
rsort(n,m); swap(rk,tp);
rk[sa[]]=; num=;
for(int i=;i<=n;i++)
{
int u=Min(n+,sa[i]+k),v=Min(n+,sa[i-]+k);//
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[u]==tp[v])?num:++num;//tp[n+1]!
}
if(num==n)break;
m=num;
}
}
void geth(int n)
{
int k=; ht[][]=;
for(int i=;i<=n;i++)
{
if(rk[i]==)continue;
if(k)k--; int j=sa[rk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
ht[rk[i]][]=k;
}
for(int i=;i<;i++)
for(int j=;j+bin[i]-<=n;j++)
ht[j][i]=Min(ht[j][i-],ht[j+bin[i-]][i-]);
}
int getlcp(int x,int y,int n)
{
if(x==y)return n-x+;
x=rk[x]; y=rk[y];
if(x>y)swap(x,y); x++;
int r=bit[y-x+];
return Min(ht[x][r],ht[y-bin[r]+][r]);
}
void psd(int t,int x,int l,int r)
{
if(!lzy[t][x])return;
int d=lzy[t][x]; lzy[t][x]=;
sum[t][ls]+=d*(mid-l+); lzy[t][ls]+=d;
sum[t][rs]+=d*(r-mid); lzy[t][rs]+=d;
}
void update(int t,int x,int l,int r,int L,int R)
{
if(L>R)return;
if(l>=L&&r<=R){sum[t][x]+=r-l+; lzy[t][x]++; return;}
psd(t,x,l,r);
if(mid>=L)update(t,ls,l,mid,L,R);
if(mid<R)update(t,rs,mid+,r,L,R);
sum[t][x]=sum[t][ls]+sum[t][rs];
}
ll query(int t,int x,int l,int r,int L,int R)
{
if(L>R)return ;
if(l>=L&&r<=R)return sum[t][x];
psd(t,x,l,r); ll ret=;
if(mid>=L)ret+=query(t,ls,l,mid,L,R);
if(mid<R)ret+=query(t,rs,mid+,r,L,R);
return ret;
}
int main()
{
int T; scanf("%d",&T);
bin[]=; for(int i=;i<;i++)bin[i]=(bin[i-]<<);
bit[]=; for(int i=;i<=6e4;i++)bit[i]=bit[i>>]+;//6e4
while(T--)
{
memset(sum,,sizeof sum);
memset(lzy,,sizeof lzy);
scanf("%s",s+); int n=strlen(s+);
s[n+]='a'-;
for(int i=n+,k=n;k;i++,k--)s[i]=s[k],op[k]=i;
work(n*+); geth(n*+); ll ans=;
for(int d=;d<=n;d++)
for(int i=;i+d<=n;i+=d)
{
int j=i+d;
int t2=Min(d,getlcp(i,j,n));
int t1=Min(d,getlcp(op[i],op[j],n));
if(t1+t2-<d)continue;
int l=i-t1+,r=i+t2-d;//hd
ans+=query(,,,n,Max(,l-),r-);//qtl
ans+=query(,,,n,l+*d,Min(n,r+*d));//qhd
update(,,,n,l,r); update(,,,n,l+*d-,r+*d-);
}
printf("%lld\n",ans);
}
return ;
}
bzoj 4650 & 洛谷 P1117 优秀的拆分 —— 枚举关键点+后缀数组的更多相关文章
- 洛谷P1117 优秀的拆分【Hash】【字符串】【二分】【好难不会】
题目描述 如果一个字符串可以被拆分为AABBAABB的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串aabaabaaaabaabaa,如果令 A=aabA ...
- 洛谷P1117 优秀的拆分
题意:求一个字符串中有多少形如AABB的子串. 解:嗯...我首先极度SB的想了一个后缀自动机套线段树启发式合并的做法,想必会TLE. 然后跑去看题解,发现实在是妙不可言... 显然要对每个位置求出向 ...
- bzoj 4650(洛谷 1117) [Noi2016]优秀的拆分——枚举长度的关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 ...
- 【洛谷 P4051】 [JSOI2007]字符加密(后缀数组)
题目链接 两眼题.. 第一眼裸SA 第二眼要复制一倍再跑SA. 一遍过.. #include <cstdio> #include <cstring> #include < ...
- bzoj 2119 股市的预测 —— 枚举关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 思路就是对于这个形如 ABA 的串,枚举 A 的长度,并按照长度分出几块,找到一些关键 ...
- 洛谷 P2404 自然数的拆分问题
题目链接 https://www.luogu.org/problemnew/show/P2404 题目背景 木有...... 题目描述 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. ...
- [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)
[BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...
- bzoj 4816: 洛谷 P3704: [SDOI2017]数字表格
洛谷很早以前就写过了,今天交到bzoj发现TLE了. 检查了一下发现自己复杂度是错的. 题目传送门:洛谷P3704. 题意简述: 求 \(\prod_{i=1}^{N}\prod_{j=1}^{M}F ...
- bzoj 1014: 洛谷 P4036: [JSOI2008]火星人
题目传送门:洛谷P4036. 题意简述: 有一个字符串,支持插入字符,修改字符. 每次需要查询两个后缀的LCP长度. 最终字符串长度\(\le 100,\!000\),修改和询问的总个数\(\le 1 ...
随机推荐
- Percona 工具包 pt-online-schema-change 简介
mysql的在线表结构修改,因为低效和阻塞读写.一直被诟病.至于ALTER TABLE 的原理,参看我上一篇文章.MySQL在线修改大表结构.看完后,发现的问题是还是会锁的,且对于在线更新的这块也是不 ...
- 【bzoj5452】[Hnoi2016]大数(莫队)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4542 首先若p=2,5则这题就是道傻逼题,前缀和搞一下没了.如果p为其他质数,那么可以 ...
- java如何调用接口
其实对于java调用接口进行获取对方服务器的数据在开发中特别常见,然而一些常用的基础的知识总是掌握不牢,让人容易忘记,写下来闲的时候看看,比回想总会好一些. 总体而言,一些东西知识点一直复制粘贴容易依 ...
- HUE中Oozie执行Hive脚本
Oozie执行hive,传入参数1. 新建一个workflow 2. 拖入一个hive2 3. hive脚本如下 CREATE TABLE IF NOT EXISTS spider_tmp.org_i ...
- Linux系统官网下载
CentOS-6.9-x86_64-bin-DVD1.isohttp://archive.kernel.org/centos-vault/6.9/isos/x86_64/CentOS-6.9-x86_ ...
- Hibernate -- 配置c3p0连接池, 事务隔离级别, 管理session
知识点1:配置c3p0连接池(了解) * 引入c3p0-0.9.1.jar * 在hibernate.cfg.xml文件中增加如下配置 <!-- C3P0连接池设定--> <!-- ...
- 智课雅思词汇---二十三、名词性后缀mony
智课雅思词汇---二十三.名词性后缀mony 一.总结 一句话总结:Latin: action, result of an action or condition; a suffix that for ...
- spring3: 依赖和依赖注入-xml配置-DI的配置
3.1.1 依赖和依赖注入 传统应用程序设计中所说的依赖一般指“类之间的关系”,那先让我们复习一下类之间的关系: 泛化:表示类与类之间的继承关系.接口与接口之间的继承关系: 实现:表示类对接口的实现 ...
- 分享知识-快乐自己:都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事
都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事 就用下面这段代码在jdk的三个版本运行看了下效果: import java.lang.reflect.Field ...
- Ceph中的容量计算与管理
转自:https://www.ustack.com/blog/ceph%ef%bc%8drongliang/ 在部署完Ceph集群之后,一般地我们可以通过Ceph df这个命令来查看集群的容量状态,但 ...