题目的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. strong 、weak、copy 、assign 、retain 、unsafe_unretained 与autoreleasing区别和作用

    strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切 @property (nonatomic, strong) NSString *stringA; @property ...

  2. 原创 :xftp SFTP子系统申请已拒绝 请确保SSH链接的SFTP子系统设置有效

    在出现这个错误时候 如果你的远程连接没有问题 那么就执行下面的命令 service sshd restart 搞定!

  3. 机器学习之-奇异值分解(SVD)原理详解及推导

    转载 http://blog.csdn.net/zhongkejingwang/article/details/43053513 在网上看到有很多文章介绍SVD的,讲的也都不错,但是感觉还是有需要补充 ...

  4. Robot Framework(十三) 执行测试用例——创建输出

    3.5创建输出 执行测试时会创建几个输出文件,并且所有这些文件都与测试结果有某种关联.本节讨论创建的输出,如何配置它们的创建位置以及如何微调其内容. 3.5.1不同的输出文件 输出目录 输出文件 日志 ...

  5. 几句话总结一个算法之RNN、LSTM和GRU

    RNN 一般神经网络隐层的计算是h=g(w * x),其中g是激活函数,相比于一般神经网络,RNN需要考虑之前序列的信息,因此它的隐藏h的计算除了当前输入还要考虑上一个状态的隐藏,h=g(w*x+w' ...

  6. 第1节 flume:13、14、更多flume案例一,通过拦截器实现不同类型的数据区分

    1.6.flume案例一 1. 案例场景 A.B两台日志服务机器实时生产日志主要类型为access.log.nginx.log.web.log 现在要求: 把A.B 机器中的access.log.ng ...

  7. angstromctf -No libc for You

    0x00 syscall syscall函数原型为: int syscall(int number, ...) 其中number是系统调用号,number后面应顺序接上该系统调用的所有参数.大概意思是 ...

  8. python-DB模块实例

    MySQLdb其实有点像php或asp中连接数据库的一个模式了,只是MySQLdb是针对mysql连接了接口,我们可以在python中连接MySQLdb来实现数据的各种操作. python连接mysq ...

  9. lucene测试类

    package test.lucene; import java.io.BufferedReader;import java.io.File;import java.io.FileInputStrea ...

  10. passive event 解决方法

    为了让页面滚动的效果如丝般顺滑,从 chrome56 开始,在 window.document 和 body 上注册的 touchstart 和 touchmove 事件处理函数,会默认为是 pass ...