题目的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-Debug-Database 在浏览器中查看App的数据库

    使用参考:http://www.jianshu.com/p/89ccae3e590b源码地址:https://github.com/amitshekhariitbhu/Android-Debug-Da ...

  2. IOS之UI异步刷新

    NSOperationQueue     *operationQueue; // for rendering pages on second thread [operationQueue waitUn ...

  3. Redis监控之redis-live.conf配置

    { "RedisServers": [ { "server": "192.168.1.201", "port": 637 ...

  4. .Net Mvc 返回Json,动态生成EasyUI Tree

    最近做一个项目,开始接触EasyUI,感觉很强大,很适合我这种对前台不是很感冒的人.在学习Tree的过程中,感觉网上的资料挺乱的,很多只是把EasyUI API 抄了一遍.现在把最近这段时间的学到的, ...

  5. HDU 3586 Information Disturbing (树形DP,二分)

    题意: 给定一个敌人的通信系统,是一棵树形,每个节点是一个敌人士兵,根节点是commander,叶子是前线,我们的目的是使得敌人的前线无法将消息传到commander,需要切断一些边,切断每条边需要一 ...

  6. 如何计算CDS view里两个时间戳之间的天数间隔

    ABAP透明表里的时间戳,数据类型为dec: 有个需求:计算这两个时间戳之间的天数间隔,丢弃时间戳年-月-日8位后面的小时:分钟:秒. 举个例子:如果时间戳是20180918173132,丢弃1731 ...

  7. UVA 10003 cuting sticks 切木棍 (区间dp)

    区间dp,切割dp[i][j]的花费和切法无关(无后效性) dp[i][j]表示区间i,j的花费,于是只要枚举切割方法就行了,区间就划分成更小的区间了.O(n^3) 四边形不等式尚待学习 #inclu ...

  8. AEE加密解密

     from Crypto.Cipher import AESfrom binascii import b2a_hex, a2b_hex class AesHandler(object):    def ...

  9. python已安装好第三方库,pycharm import时仍标红的解决办法

    pip install pymysql之后导入import pymysql时候标红 发现 pymysql下方还是标红,不能正常导入 可以试用一下以下的办法 解决办法: 首先打开 Settings找到P ...

  10. WebStorm换主题(护眼)

    一.下载喜欢颜色的主题 http://www.phpstorm-themes.com/ 我用的豆沙绿护眼 <scheme name="Solarized Light My" ...