题目的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. okhttp使用心得(https验证不通过)(一)

    之前项目使用的是okhttp3.4版本的,tls协议支持1.0 1.2 等等 后来换成okhttp3.8.1,发现握手失败 找了好多原因之后  发现吧tls加上1.0后,就可以握手成功了,但是tls1 ...

  2. 内存泄露--contentView缓存使用与ListView优化

    引起Android内存泄露有很多种原因,下面罗列了一些问题,以后会一一解决 1.构造Adapter时没有使用缓存convertView(衍生出ListView优化问题) 2.查询数据库游标没有关闭 3 ...

  3. ycsb安装和使用介绍

    nosql性能测试工具ycsb0.1的使用 使用文档参考地址:https://www.cnblogs.com/SailorXiao/p/5808828.html ycsb地址:https://gith ...

  4. gunzip

    gunzip——解压缩.gz的压缩文件 GNU unzip 命令所在路径:/bin/gunzip 示例1: # gunzip services.gz 解压缩当前目录下的services.gz文件,执行 ...

  5. Fedora19 有关输入法的无法切换问题 和 终端的快捷设置问题

    Fedora19 有关输入法的无法切换问题 和 终端的快捷设置问题 1.首先,要单击右上角的设置输入法的"区域与语言设置",要设置为“为每个窗口设置不同的输入源”. 还有,刚使用的 ...

  6. softmax_loss

    softmax_loss中的ignore_label是来自于loss layer,而不是softmax_loss的参数

  7. pb2.text_format.Merge(f.read(), self.solver_param) AttributeError: 'module' object has no attribute 'text_format'

    http://blog.csdn.net/qq_33202928/article/details/72526710

  8. Hibernate查询语句HQL8大特点

    Hibernate拥有一种功能非常强大的查询语言,这种语言被有意得与SQL非常相似,便于开发人员掌握.但不要被HQL的语法表面所迷惑,HQL完全是面向对象的,可以用来过程多态.继承.关联等关系. 1. ...

  9. 正则表达式匹配:根据key获取value

    需求 url请求html字符串,dytk值写在js里,可以看成是key-value的格式,需要提取dytk值. 解决方法 正则匹配 private string get_dytk(string htm ...

  10. Java多线程编程核心(1)

    Java多线程编程核心(1) 停止线程 本节主要讨论如何更好停止一个线程.停止线程意味着在线程处理完成任务之前放弃当前操作. 1.停不了的线程 可能大多数同学会使用interrupt()来停止线程,但 ...