原文链接http://www.cnblogs.com/zhouzhendong/p/9033092.html

题目传送门 - BZOJ3230

题意

  给定字符串$s$。长度为$n$。

  现在有$Q$组询问,每组询问内容如下:

  两个正整数$i,j$。

  设$s_i,s_j$分别表示$s$的所有本质不同的子串中字典序第$i$小和第$j$小的子串。

  请你输出$|lcp(s_i,s_j)|^2+|lcs(s_i,s_j)|^2$。

  如果不存在$s_i$或者$s_j$,则输出$-1$。

  $n,Q\leq 10^5$

题解

  这题大概是我做的前几题$SA$的大整合+升级版吧。

  我们考虑如何找到本质不同子串中第$k$大的子串。

  我们考虑按照串$s$的后缀大小从小到大处理。

  对于排名为$i$的后缀$SA[i]$,考虑它 除了与排名更靠前的其他后缀 的相同前缀以外的前缀所代表的子串。

  很显然,这些子串都是本质不同的。根据后缀数组的性质,也很显然,这些串都不同于之前已经计算过的串。不然的话,$height[i]$会更大。

  而且,这些子串是按照字典序排的。

  现在,我们发现这些后,不需要处理出所有子串。

  统计原串后缀排名前$i$的后缀所包含的子串的个数,记为$presum[i]$。

  显然,$presum[i]=presum[i-1]+len(SA[i])-height[i]$。

  于是我们在查找第$k$大子串的时候就可以通过二分或者倍增来快速地找到第$k$大的子串所在的后缀,然后确定第$k$大的子串就容易了。

  至于求两个子串的$LCP$和$LCS$长度,是后缀数组的经典操作,这里就不加赘述了。

代码

#include <bits/stdc++.h>
#define rank r_a_n_k
using namespace std;
typedef long long LL;
const int N=200005;
int n,Q;
int SA[N],rank[N],height[N],tax[N],tmp[N];
int sSA[N],srank[N],sheight[N];
int ST[N][19];
LL presum[N];
char s[N];
void Sort(int n,int m,int SA[],int rank[]){for (int i=0;i<=m;i++)tax[i]=0;for (int i=1;i<=n;i++)tax[rank[i]]++;for (int i=1;i<=m;i++)tax[i]+=tax[i-1];for (int i=n;i>=1;i--)SA[tax[rank[tmp[i]]]--]=tmp[i];
}
bool cmp(int rk[],int x,int y,int w){return rk[x]==rk[y]&&rk[x+w]==rk[y+w];
}
void Suffix_Array(char s[],int n,int SA[],int rank[],int height[]){memset(SA,0,sizeof SA);memset(tmp,0,sizeof tmp);memset(rank,0,sizeof rank);memset(height,0,sizeof height);for (int i=1;i<=n;i++)rank[i]=s[i],tmp[i]=i;int m=127;Sort(n,m,SA,rank);for (int w=1,p=0;p<n;w<<=1,m=p){p=0;for (int i=n-w+1;i<=n;i++)tmp[++p]=i;for (int i=1;i<=n;i++)if (SA[i]>w)tmp[++p]=SA[i]-w;Sort(n,m,SA,rank);for (int i=1;i<=n;i++)swap(rank[i],tmp[i]);rank[SA[1]]=p=1;for (int i=2;i<=n;i++)rank[SA[i]]=cmp(tmp,SA[i],SA[i-1],w)?p:++p;}for (int i=1,j,k=0;i<=n;height[rank[i++]]=k)for (k=max(k-1,0),j=SA[rank[i]-1];s[i+k]==s[j+k];k++);height[1]=0;
}
void Get_ST(int n){memset(ST,0,sizeof ST);for (int i=1;i<=n;i++){ST[i][0]=height[i];for (int j=1;j<19;j++){ST[i][j]=ST[i][j-1];if (i-(1<<(j-1))>0)ST[i][j]=min(ST[i][j],ST[i-(1<<(j-1))][j-1]);}}
}
int Query(int L,int R){int val=floor(log(R-L+1)/log(2));return min(ST[L+(1<<val)-1][val],ST[R][val]);
}
int LCP(int x,int y){if (x==y)return n;x=rank[x],y=rank[y];return Query(min(x,y)+1,max(x,y));
}
int LCS(int x,int y){return LCP(n*2+2-x,n*2+2-y);
}
void GetSubstr(LL k,int &L,int &R){int pos,i;for (pos=0,i=19;i>=0;i--)if (pos+(1<<i)<n&&presum[pos+(1<<i)]<k)pos+=(1<<i);L=sSA[pos+1];R=1LL*L+k-presum[pos]+sheight[pos+1]-1;
}
int main(){scanf("%d%d",&n,&Q);scanf("%s",s+1);s[n+1]='#';for (int i=n*2+1;i>n+1;i--)s[i]=s[n*2+2-i];Suffix_Array(s,n*2+1,SA,rank,height);Get_ST(n*2+1);for (int i=n+1;i<=n*2+1;i++)s[i]=0;Suffix_Array(s,n,sSA,srank,sheight);presum[0]=0;for (int i=1;i<=n;i++)presum[i]=presum[i-1]+(n-sSA[i]+1)-sheight[i];while (Q--){LL k1,k2;int L1,R1,L2,R2;scanf("%lld%lld",&k1,&k2);if (k1>presum[n]||k2>presum[n]){puts("-1");continue;}GetSubstr(k1,L1,R1);GetSubstr(k2,L2,R2);LL len=min(R1-L1+1,R2-L2+1);LL lcp=min(len,(LL)LCP(L1,L2)),lcs=min(len,(LL)LCS(R1,R2));printf("%lld\n",lcp*lcp+lcs*lcs);}return 0;
}

  

转载于:https://www.cnblogs.com/zhouzhendong/p/BZOJ3230.html

BZOJ3230 相似子串 字符串 SA ST表相关推荐

  1. BZOJ3172 [Tjoi2013]单词 字符串 SA ST表

    原文链接http://www.cnblogs.com/zhouzhendong/p/9026543.html 题目传送门 - BZOJ3172 题意 输入$n(n\leq 200)$个字符串,保证长度 ...

  2. [SDOI2016] 生成魔咒(后缀数组SA + st表 + set)动态不同子串个数

    problem luogu-P4070 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1,21,21,2 拼凑起来形成一个魔咒串 [1,2][1,2][1,2]. 一个魔咒串 ...

  3. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  4. 洛谷P4094 [HEOI2016/TJOI2016]字符串【后缀数组+主席树+st表】

    时空限制 2000ms / 256MB 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确 ...

  5. sa后缀数组使用合集,包括height数组求LPC和LCS,ST表,单调队列优化。

    P5546 [POI2000]公共串 所有串合在一起,每两个串放不同的字符,求一遍后缀数组,然后利用height数组求LCS即可. #include<iostream> #include& ...

  6. [BZOJ3230]相似子串

    [BZOJ3230]相似子串 试题描述 输入 输入第1行,包含3个整数N,Q.Q代表询问组数. 第2行是字符串S. 接下来Q行,每行两个整数i和j.(1≤i≤j). 输出 输出共Q行,每行一个数表示每 ...

  7. 后缀数组 ---- 2018~2019icpc焦作H题[后缀数组+st表+二分+单调栈]

    题目链接 题目大意: 给出nnn个数,定义f[l,r]f[l,r]f[l,r]表示 区间[l,r][l,r][l,r]的最大值,求所有 子区间的最大值的和,要求相同的子区间只能算一次 比如数列 5 6 ...

  8. UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组、ST表)

    UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组.ST表) 连NOI Day1T1都不会做...看了题解都写不出来还要抄Claris的代码.. 题 ...

  9. bzoj3277 串 (后缀数组+二分答案+ST表)

    常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...

最新文章

  1. TensorRT Analysis Report分析报告
  2. Spring 教程(三) 环境设置
  3. 谷歌出现新冠肺炎确诊病例,限制员工出行;比尔·盖茨:可能成百年不遇的大流行病...
  4. 【数据挖掘】基于密度的聚类方法 - DBSCAN 方法 ( DBSCAN 原理 | DBSCAN 流程 | 可变密度问题 | 链条现象 | OPTICS 算法引入 | 聚类层次 | 族序概念 )
  5. dofuscator C# 混淆器 原来如此
  6. UA MATH565C 随机微分方程III Ito积分简介
  7. Python3_实例汇总
  8. 深入学习 History 对象管理浏览器会话历史
  9. security和oauth2.0的整合
  10. 将Android源码集成到Eclipse中的方法
  11. 在SpringBoot中使用slf4j与logbak
  12. 云服务器预装什么系统好,云服务器预装什么系统好
  13. php学习的一些笔记
  14. 旅游规划 (25 分)(Dijkstra)
  15. MVC3开发常常遇到的问题及常常使用到的代码片段
  16. 【终终极版】linux(Ubuntu)下wineQQ的安装办法
  17. 暗黑破坏神不朽怎么在电脑上玩 暗黑破坏神不朽模拟器教程
  18. 高级程序员的思维模式
  19. 大数据周周看:金融科技公司融360赴美IPO,小蓝单车人去楼空,用户押金退还困难
  20. Mysql上线长时间以后重新发起请求报错

热门文章

  1. ArcGIS Server for Silverlight 之集群(Simple Clusterer)
  2. idea中刷新项目快捷键_解决 IDEA 使用过程中让你觉得不爽的一些问题
  3. mysql表只有frm文件_MYSQL数据文件--.frm文件(只有.frm文件时的表结构恢复)
  4. 011_TreeMap对键实现了Comparable接口的对象排序
  5. android 数据存储怎么保存图片_遇到验证码怎么办?Python编写一个验证码图片数据标注GUI程序!...
  6. 蓝湖怎么切图标注_【蓝湖指北】一张图教你如何选择标注尺寸
  7. Windows 上看端口 找PID
  8. Packt.Java.9.High.Performance.2017.11
  9. docker 保存 环境持久化_18、docker的持久化存储和数据共享
  10. oracle 的目录是空的,oracle sqlplus在@命令路径中有空格的问题