题目的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 相似子串 ——后缀数组的更多相关文章

  1. BZOJ 3230 相似子串 | 后缀数组 二分 ST表

    BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...

  2. bzoj 3230 相似子串——后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 作出后缀数组,从 LCP 看每个位置对于本质不同子串的贡献,而且他们已经按前面部分排好 ...

  3. BZOJ 3230: 相似子串(后缀数组)

    传送门 解题思路 其实题目挺好想的.首先子串排名可以由后缀数组求得,因为不算重复的,所以后缀数组的每个后缀排名的去掉\(lcp\)的前缀排名为当前后缀的子串排名.这样就可以预处理出每个后缀的\(l,r ...

  4. bzoj 3230 相似子串 —— 后缀数组+二分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 先算出每个后缀贡献子串的区间: 然后前缀LCP直接查询,后缀LCP二分长度,查询即可: ...

  5. BZOJ 1396: 识别子串( 后缀数组 + 线段树 )

    这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...

  6. poj 2774 最长公共子串 后缀数组

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25752   Accepted: 10 ...

  7. URAL 1297 最长回文子串(后缀数组)

    1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...

  8. poj 1743 Musical Theme(最长重复子串 后缀数组)

    poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...

  9. BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

    二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...

随机推荐

  1. Android中的ListView属性使用总结

    Android中使用ListView控件比较常见,如果能知道常用的一些属性使用,肯定会少很多坑. 1.ListView是常用的显示控件,默认背景是和系统窗口一样的透明色,如果给ListView加上背景 ...

  2. Sqlserver 2012 Always on技术

    使用了Sqlserver 2012 Always on技术后,假如采用的配置是默认配置,会出现Primary server CPU很高的情况发生,比如默认配置如下: 需要自定义来解决这个问题. 我们先 ...

  3. 【Codeforces Rockethon 2014】Solutions

    转载请注明出处:http://www.cnblogs.com/Delostik/p/3553114.html 目前已有[A B C D E] 例行吐槽:趴桌子上睡着了 [A. Genetic Engi ...

  4. HITICS || 2018大作业 程序人生 Hello's P2P

    摘  要 本文通过分析一个hello.c的完整的生命周期,从它开始被编译,到被汇编.链接.在进程中运行,讲解了Linux计算机系统执行一个程序的完整过程. 关键词:操作系统,进程,程序的生命周期 目 ...

  5. 玩4K必备知识:HDMI1.4、2.0、2.0a、2.0b接口参数对比【扫盲贴】

    https://www.4k123.com/thread-55369-1-1.html 前言:玩4K的同学都知道,HDMI接口是视频传输最常用的接口,但是这个接口却有好几个版本HDMI1.4.HDMI ...

  6. jQuery绑定动态元素的点击事件无效

    之前就一直受这个问题的困扰,在写ajax加载数据的时候发现,后面追加进来的demo节点元素,失去了之前的点击事件.为什么点击事件失效,我们该怎么去解决呢?那么,我们通过下面的示例简单说明. 示例如下: ...

  7. Linux网卡设置为网桥模式

    Linux网卡设置为网桥模式 1.    添加网卡,并修改相关配置文件 1.1虚拟机添加网卡,并配置相关文件 如:eth2为新添加网卡 cd /etc/sysconfig/network-script ...

  8. LeetCode 最大子序和

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 ...

  9. hihoCoder-1098-kruskal

    如果起始点和终止点的父节点相同,就说明它们就已经在同一个连通分量里面,说明,起始点和终止点在此之前就已经被连入同一个分量之中,如果此时还将起始点和终止点连入此分量,就会形成回路,想象一个三角形,你大概 ...

  10. linux中进程亲和性绑定

    什么是绑核所谓绑核,其实就是设定某个进程/线程与某个CPU核的亲和力(affinity).设定以后,Linux调度器就会让这个进程/线程只在所绑定的核上面去运行.但并不是说该进程/线程就独占这个CPU ...