BZOJ 3230 相似子串 ——后缀数组
题目的Source好有趣。
我们求出SA,然后求出每一个后缀中与前面本质不同的字符串的个数。
然后二分求出当前的字符串。
然后就是正反两次后缀数组求LCP的裸题了。
要注意,这时两个串的起点可能会相同,所以需要判掉。
无论读入还是输出都有可能爆long long,要注意
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #define F(i,j,k) for (int i=j;i<=k;++i)
- #define D(i,j,k) for (int i=j;i>=k;--i)
- #define maxn 200500
- #define inf 0x3f3f3f3f
- #define ll long long
- int _log2[maxn];
- struct Suffix_Array{
- int s[maxn],cnt[maxn],tmp[maxn],sa[maxn],h[maxn],rk[maxn];
- int st[maxn][21];
- ll pre[maxn],Sum;
- void build(int n,int m)
- {
- n++; int i,j,k;
- F(i,0,2*n+5) sa[i]=tmp[i]=h[i]=rk[i]=0;
- F(i,0,m-1) cnt[i]=0;
- F(i,0,n-1) cnt[rk[i]=s[i]]++;
- F(i,1,m-1) cnt[i]+=cnt[i-1];
- F(i,0,n-1) sa[--cnt[rk[i]]]=i;
- for (k=1;k<=n;k<<=1)
- {
- F(i,0,n-1) {j=sa[i]-k;if(j<0)j+=n;tmp[cnt[rk[j]]++]=j;}
- sa[tmp[cnt[0]=0]]=j=0;
- F(i,1,n-1)
- {
- if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
- sa[tmp[i]]=j;
- }
- memcpy(rk,sa,n*sizeof(int));memcpy(sa,tmp,n*sizeof(int));
- if (j>=n-1) break;
- }
- for (i=k=0;i<n;h[rk[i++]]=k)
- for (k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
- F(i,0,n-1) st[i][0]=h[i];
- F(i,1,20) F(j,0,n-(1<<i)) st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
- F(i,1,n-1) pre[i]=pre[i-1]+n-sa[i]-h[i]-1;
- Sum=pre[n-1];
- }
- int query(int l,int r)
- {
- int t=_log2[r-l+1];
- return min(st[l][t],st[r-(1<<t)+1][t]);
- }
- ll lcp(int a,int b)
- {
- if (a==b) return inf;
- int aa=rk[a],bb=rk[b];
- return query(min(aa,bb)+1,max(aa,bb));
- }
- void find(ll x,int n,int &l,int &r)
- {
- int le=1,ri=n;
- while (le<ri)
- {
- int mid=le+ri>>1;
- if (pre[mid]>=x) ri=mid;
- else le=mid+1;
- }
- int tmp=x-pre[le-1]+h[le];
- l=sa[le];r=l+tmp-1;
- }
- }SA,SB;
- int n,q;
- char s[maxn];
- int main()
- {
- F(i,2,maxn-1) _log2[i]=_log2[i>>1]+1;
- scanf("%d%d",&n,&q);
- scanf("%s",s);
- F(i,0,n-1)
- {
- SA.s[i]=s[i]-'a'+1;
- SB.s[n-i-1]=s[i]-'a'+1;
- }
- SA.s[n]=0; SB.s[n]=0;
- SA.build(n,30); SB.build(n,30);
- F(i,1,q)
- {
- ll x,y;
- int xl,xr,yl,yr;
- scanf("%lld%lld",&x,&y);
- if (x>SA.Sum||y>SA.Sum) {printf("-1\n");continue;}
- SA.find(x,n,xl,xr); SA.find(y,n,yl,yr);
- ll lcp=SA.lcp(xl,yl),rcp=SB.lcp(n-yr-1,n-xr-1);
- int l=min(xr-xl+1,yr-yl+1); lcp=min(lcp,(ll)l); rcp=min(rcp,(ll)l);
- printf("%lld\n",lcp*lcp+rcp*rcp);
- }
- }
BZOJ 3230 相似子串 ——后缀数组的更多相关文章
- BZOJ 3230 相似子串 | 后缀数组 二分 ST表
BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...
- bzoj 3230 相似子串——后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 作出后缀数组,从 LCP 看每个位置对于本质不同子串的贡献,而且他们已经按前面部分排好 ...
- BZOJ 3230: 相似子串(后缀数组)
传送门 解题思路 其实题目挺好想的.首先子串排名可以由后缀数组求得,因为不算重复的,所以后缀数组的每个后缀排名的去掉\(lcp\)的前缀排名为当前后缀的子串排名.这样就可以预处理出每个后缀的\(l,r ...
- bzoj 3230 相似子串 —— 后缀数组+二分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 先算出每个后缀贡献子串的区间: 然后前缀LCP直接查询,后缀LCP二分长度,查询即可: ...
- BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...
- poj 2774 最长公共子串 后缀数组
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 25752 Accepted: 10 ...
- URAL 1297 最长回文子串(后缀数组)
1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
随机推荐
- Azure 项目构建 – 部署 Jenkins 服务器以实现持续集成(CI)
通过完整流程详细介绍了如何通过 Azure 虚拟机.虚拟网络等服务在 Azure 平台上快速搭建 Jenkins 服务器. 此系列的全部课程 https://school.azure.cn/curri ...
- selenium-Python之定位下拉框选择
1.通过select 进行定位下拉框 下拉框如图所示 通过代码定位 #通过index进行选择Select(driver.find_element_by_id("cardType") ...
- Spring 配置定时器(注解+xml)方式—整理
一.注解方式 1. 在Spring的配置文件ApplicationContext.xml,首先添加命名空间 xmlns:task="http://www.springframework.or ...
- windows8无脑式双系统安装教程(转)
转:http://blog.csdn.net/poem_qianmo/article/details/7334987 首先去微软官网将ISO文件下载下来,分为32bit跟64bit两个版本,因人而异, ...
- URAL 2048 Histroy(打表+模拟)
因为年历是400年一个循环节的,所以递推出一年的情况,然后递推处理出一个循环节的情况.对于询问,求一个类似前缀和的东西就好了. 跑出来和比样例小一,把A和B加一以后交后AC... 写得时候注意变量的定 ...
- 转向ARC的说明
转自hherima的博客原文:Transitioning to ARC Release Notes(苹果官方文档) ARC是一个编译器特征,它提供了对OC对象自动管理内存.ARC让开发者专注于感兴趣的 ...
- struts2的动态方法配置
动态方法调用配置 <package name="test" extends="struts-default"> <aciton name=&q ...
- c++ 结构体,设置物品体积并输出物品属性
#include <iostream> using namespace std; struct box { char maker[40]; float height; float widt ...
- GIMP里的Path移动,旋转,翻转操作
1/Path的移动: 快捷键Ctrl+Move Tool 2/Path的旋转: 选择Rotate Tool,在Path中选择,出现十字圈. Angel下的滑块调节一定的角度,在合适的位置即可. 3/P ...
- python基础知识13-迭代器与生成器,导入模块
异常处理作业讲解 file = open('/home/pyvip/aaa.txt','w+') try: my_dict = {'name':'adb'} file.write(my_dict['a ...