题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230

先算出每个后缀贡献子串的区间;

然后前缀LCP直接查询,后缀LCP二分长度,查询即可;

注意本质不同的子串的个数是 long long 级别!!

于是读入有 long long —— 快读也要写成 long long 的!!!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=1e5+;
int n,m,sa[xn],rk[xn],tax[xn],tp[xn],ht[xn][],bin[],bit[xn];
ll pl[xn],pr[xn],cnt;//ll!
char s[xn];
ll rd()//ll
{
ll ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void Rsort()
{
for(int i=;i<=m;i++)tax[i]=;
for(int i=;i<=n;i++)tax[rk[tp[i]]]++;
for(int i=;i<=m;i++)tax[i]+=tax[i-];
for(int i=n;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];
}
void work()
{
for(int i=;i<=n;i++)rk[i]=s[i],tp[i]=i;
Rsort();
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;i++)tp[++num]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++num]=sa[i]-k;
Rsort(); swap(rk,tp);
rk[sa[]]=; num=;
for(int i=;i<=n;i++)
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[sa[i]+k]==tp[sa[i-]+k])?num:++num;
if(num==n)break;
m=num;
}
}
void get()
{
int k=;
for(int i=;i<=n;i++)
{
if(rk[i]==)continue;
if(k)k--; int j=sa[rk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
ht[rk[i]][]=k;
}
bin[]=; for(int i=;i<;i++)bin[i]=(bin[i-]<<);
bit[]=; for(int i=;i<=xn;i++)bit[i]=bit[i>>]+;
for(int j=;j<;j++)
for(int i=;i<=n&&i+bin[j]-<=n;i++)
ht[i][j]=min(ht[i][j-],ht[i+bin[j-]][j-]);
}
int getlcp(int x,int y)
{
if(x==y)return n-x+;
x=rk[x]; y=rk[y];
if(x>y)swap(x,y); x++;
int w=bit[y-x+];
return min(ht[x][w],ht[y-bin[w]+][w]);
}
void init()
{
for(int i=;i<=n;i++)
{
ll num=n-sa[i]+-ht[i][];
pl[i]=cnt+; cnt+=num; pr[i]=cnt;
}
}
void find(ll x,int &sl,int &sr)
{
int l=,r=n,res;
while(l<=r)
{
int mid=((l+r)>>);
if(x>=pl[mid]&&x<=pr[mid]){res=mid; sl=sa[mid]; break;}//mid:rk
if(x<pl[mid])r=mid-;
else l=mid+;
}
int st=sl+ht[res][];
sr=st+(x-pl[res]+)-;
}
int ask(int x,int y)
{
int l=,r=min(x,y),res;//min
while(l<=r)
{
int mid=((l+r)>>);
if(getlcp(x-mid+,y-mid+)>=mid)res=mid,l=mid+;
else r=mid-;
}
return res;
}
int main()
{
n=rd(); int Q=rd();
scanf("%s",s+); m=;
work(); get(); init();
for(int i=;i<=Q;i++)
{
ll x=rd(),y=rd();//ll
if(x>cnt||y>cnt){puts("-1"); continue;}
int l1,r1,l2,r2; find(x,l1,r1); find(y,l2,r2);
int mnn=min(r1-l1+,r2-l2+);
int a=min(getlcp(l1,l2),mnn);
int b=min(ask(r1,r2),mnn);
printf("%lld\n",(ll)a*a+(ll)b*b);
}
return ;
}

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 相似子串 ——后缀数组

    题目的Source好有趣. 我们求出SA,然后求出每一个后缀中与前面本质不同的字符串的个数. 然后二分求出当前的字符串. 然后就是正反两次后缀数组求LCP的裸题了. 要注意,这时两个串的起点可能会相同 ...

  5. BZOJ 4278: [ONTAK2015]Tasowanie (后缀数组 / 二分+hash)

    直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门- 但是本蒟蒻不会后缀数组 Upd:Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2 ...

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

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

  7. 【BZOJ3230】相似子串 后缀数组+二分+RMQ

    [BZOJ3230]相似子串 Description Input 输入第1行,包含3个整数N,Q.Q代表询问组数.第2行是字符串S.接下来Q行,每行两个整数i和j.(1≤i≤j). Output 输出 ...

  8. BZOJ3230 相似子串[后缀数组+二分+st表]

    BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...

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

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

随机推荐

  1. 关于erlang的-run 的启动参数

    在github上,关于erlang的一致性hash,有erlang-ryng和 hash_ring .在这里先聊下erlang-ryng这个. 在erlang-ryng的启动方式上,github上提供 ...

  2. BZOJ 1002 FJOI2007 轮状病毒 递推+高精度

    题目大意:轮状病毒基定义如图.求有多少n轮状病毒 这个递推实在是不会--所以我选择了打表找规律 首先执行下面程序 #include<cstdio> #include<cstring& ...

  3. 【转】一步一步带你反编译apk,并教你修改smali和重新打包

    一.工具介绍: 1.apktool:aapt.exe,apktool.bat,apktool.jar;三个在同一目录结合使用,用来反编译apk,apk重新打包: 2.dex2jar:该工具作用是将cl ...

  4. Hadoop常见异常及其解决方式

    1.Shell$ExitCodeException 现象:执行hadoop job时出现例如以下异常: 14/07/09 14:42:50 INFO mapreduce.Job: Task Id : ...

  5. jQuery中slideToggle()的详细使用方法和解释

    $(selector).slideToggle(speed,callback) 参数       speed和callback Speed  可选.规定元素从隐藏到显示的速度,默认‘normal’可能 ...

  6. 【BZOJ4861】[Beijing2017]魔法咒语 矩阵乘法+AC自动机+DP

    [BZOJ4861][Beijing2017]魔法咒语 题意:别看BZ的题面了,去看LOJ的题面吧~ 题解:显然,数据范围明显的分成了两部分:一个是L很小,每个基本词汇长度未知:一个是L很大,每个基本 ...

  7. EasyPlayerPro Windows流媒体播放器(RTSP/RTMP/HTTP/HLS/File/TCP/RTP/UDP都能播)发布啦

    EasyPlayerPro简介 EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放.支持本地文件播放,支持本地 ...

  8. function declarations are hoisted and class declarations are not 变量提升

    Classes - JavaScript | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes ...

  9. HDFS relaxes a few POSIX requirements to enable streaming access to file system data

    https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html Introduction [ ...

  10. mybatis 执行查询时报错 【Error querying database. Cause: java.sql.SQLException: Error setting driver on UnpooledDataSource. Cause: java.lang.ClassNotFoundException: Cannot find class: 】

    org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.sql.SQLE ...