bzoj 3230 相似子串 —— 后缀数组+二分
题目: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 相似子串 —— 后缀数组+二分的更多相关文章
- BZOJ 3230 相似子串 | 后缀数组 二分 ST表
BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...
- bzoj 3230 相似子串——后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 作出后缀数组,从 LCP 看每个位置对于本质不同子串的贡献,而且他们已经按前面部分排好 ...
- BZOJ 3230: 相似子串(后缀数组)
传送门 解题思路 其实题目挺好想的.首先子串排名可以由后缀数组求得,因为不算重复的,所以后缀数组的每个后缀排名的去掉\(lcp\)的前缀排名为当前后缀的子串排名.这样就可以预处理出每个后缀的\(l,r ...
- BZOJ 3230 相似子串 ——后缀数组
题目的Source好有趣. 我们求出SA,然后求出每一个后缀中与前面本质不同的字符串的个数. 然后二分求出当前的字符串. 然后就是正反两次后缀数组求LCP的裸题了. 要注意,这时两个串的起点可能会相同 ...
- BZOJ 4278: [ONTAK2015]Tasowanie (后缀数组 / 二分+hash)
直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门- 但是本蒟蒻不会后缀数组 Upd:Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2 ...
- BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...
- 【BZOJ3230】相似子串 后缀数组+二分+RMQ
[BZOJ3230]相似子串 Description Input 输入第1行,包含3个整数N,Q.Q代表询问组数.第2行是字符串S.接下来Q行,每行两个整数i和j.(1≤i≤j). Output 输出 ...
- BZOJ3230 相似子串[后缀数组+二分+st表]
BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
随机推荐
- HTML元素定位
一切皆为框 div.h1 或 p 元素常常被称为块级元素(block element).这意味着这些元素显示为一块内容,即"块框".与之相反,span 和 strong 等元素称为 ...
- requestWindowFeature使用详解
requestWindowFeature可以设置的值有: // 1.DEFAULT_FEATURES:系统默认状态,一般不需要指定 // 2.FEATURE_CONTEXT_MENU:启 ...
- linux SPI驱动——gpio模拟spi驱动(三)
一:首先在我的平台注册platform_device,保证能让spi-gpio.c能执行到probe函数. 1: struct spi_gpio_platform_data { 2: unsigned ...
- MySQL 5.7.18的安装及主从复制(主从同步)
MySQL 5.7.18的安装与主从复制 IP 计算机名 角色 192.168.1.222 001 master 192.168.1.233 002 slave CentOS 6.9安装mysql5. ...
- HDU 5338(ZZX and Permutations-用线段树贪心)
ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ...
- 1213 - Deadlock found when trying to get lock; try restarting transaction
1213 - Deadlock found when trying to get lock; try restarting transaction 出现这个原因要记住一点就是:innodb的行锁 和解 ...
- iOS应用上架报错解决
ERROR ITMS-90087: "Unsupported Architectures. The executable for LiveStorage.app/Frameworks/Spe ...
- Coursera公开课Functional Programming Principles in Scala习题解答:Week 2
引言 OK.时间非常快又过去了一周.第一周有五一假期所以感觉时间绰绰有余,这周中间没有假期仅仅能靠晚上加周末的时间来消化,事实上还是有点紧张呢! 后来发现每堂课的视频还有相应的课件(Slide).字幕 ...
- ABAP-创建客户
CALL METHOD CMD_EI_API=>MAINTAIN_BAPI FUNCTION Z_CS_RFC_OA002 . *"------------------------ ...
- Java for LeetCode 097 Interleaving String 【HARD】
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 ...