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) -------------------------------------------------- ...
随机推荐
- ios自定义日期、时间、城市选择器
选择器,我想大家都不陌生,当需要用户去选择某些范围值内的一个固定值时,我们会采用选择器的方式.选择器可以直观的提示用户选择的值范围.统一信息的填写格式,同时也方便用户快速的进行选择,比如对于性别,正常 ...
- pyhton中的__new__和__init__
首先__new__() 函数只能用于从object继承的新式类:其次,object将__new__()方法定义为静态方法,并且至少需要传递一个参数cls,cls表示需要实例化的类,此参数在实例化时由P ...
- HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
题意: 每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短. 思路: 给了很多重边,选最小的留下即可.任意点可能无法直接到达, ...
- gunzip
gunzip——解压缩.gz的压缩文件 GNU unzip 命令所在路径:/bin/gunzip 示例1: # gunzip services.gz 解压缩当前目录下的services.gz文件,执行 ...
- make与makefile的几个例子和(自己写一下,汗!忘记了!)总结
共用的几个源代码文件: main.c 2.c 3.c 代码依次为: #include<stdlib.h> #include "a.h" extern void func ...
- Asp.Net Core 入门(六)—— 路由
Asp.Net Core MVC的路由在Startup.cs文件中的Configure方法中进行配置,使其加入到Http请求管道中,如果不配置,那么我们所发送的请求无法得到象应. 那么该怎么配置Asp ...
- Python基础篇 -- 小数据池和再谈编码
小数据池 1. id() 通过id()可以查看到一个变量表示的值在内存中的地址 s = "Agoni" print(id(s)) # 2410961093272 2. is 和 = ...
- iOS利用UIDocumentInteractionController和Quick Look打开或预览文档
在App的开发过程中,我们避免不了要打开软件中的文件,例如:Excel文件,Word文件,图片文件等不同格式的文件或者想要通过第三方的App来打开这些文件,那么我们就要用到UIDocumentInte ...
- vue新手入坑之mounted和created的区别(生命周期)
这几个月用vue框架新做了一个项目,也算是边学习边实践吧.学习中也看过一些别人的开源项目,起初对mounted和created有一些疑惑,查询相关资料发现,这和vue的生命周期有关,在此也就做一个总结 ...
- laravel使用总结(二)
Mysql Eloquent 模型 新建Model 对应 表前缀 + 类名称 + s namespace App; use Illuminate\Database\Eloquent\Model; cl ...