2018.11.30 bzoj3230: 相似子串(后缀数组)
传送门
后缀数组入门题。
建立正反两个后缀数组算就行了。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,q,sa2[N],Log[N],cnt[N];
ll num[N];
char s[N];
struct SA{
int sa[N],rk[N],ht[N],st[N][21];
inline void Sort(){
for(ri i=1;i<=m;++i)cnt[i]=0;
for(ri i=1;i<=n;++i)++cnt[rk[i]];
for(ri i=2;i<=m;++i)cnt[i]+=cnt[i-1];
for(ri i=n;i;--i)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void getsa(){
for(ri i=1;i<=n;++i)rk[i]=s[i]-'a'+1,sa2[i]=i;
m=26,Sort();
for(ri w=1,p=0;m^n;w<<=1,p=0){
for(ri i=n-w+1;i<=n;++i)sa2[++p]=i;
for(ri i=1;i<=n;++i)if(sa[i]>w)sa2[++p]=sa[i]-w;
Sort(),swap(sa2,rk),rk[sa[1]]=p=1;
for(ri i=2;i<=n;++i)rk[sa[i]]=(sa2[sa[i]]==sa2[sa[i-1]]&&sa2[sa[i]+w]==sa2[sa[i-1]+w])?p:++p;
m=p;
}
for(ri i=1,j,k=0;i<=n;ht[rk[i++]]=k)for(k?--k:k,j=sa[rk[i]-1];s[i+k]==s[j+k];++k);
for(ri i=1;i<=n;++i)st[i][0]=ht[i];
for(ri j=1;j<=20;++j)for(ri i=1;i+(1<<j)-1<=n;++i)st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
inline int rmq(int l,int r){return min(st[l][Log[r-l+1]],st[r-(1<<Log[r-l+1])+1][Log[r-l+1]]);}
inline int query(int l,int r){
l=rk[l],r=rk[r];
if(l>r)l^=r,r^=l,l^=r;
return rmq(l+1,r);
}
}A,B;
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline void solve(int&l,int&r,ll k){
int id=lower_bound(num+1,num+n+1,k)-num;
l=A.sa[id],r=A.sa[id]+A.ht[id]+k-num[id-1]-1;
}
int main(){
freopen("lx.in","r",stdin);
n=read(),q=read(),scanf("%s",s+1),Log[0]=-1,A.getsa(),reverse(s+1,s+n+1),B.getsa();
for(ri i=1;i<=n;++i)Log[i]=Log[i>>1]+1,num[i]=num[i-1]+(ll)(n-A.sa[i]+1-A.ht[i]);
while(q--){
ll a=read(),b=read(),sum=0,ans;
if(a>num[n]||b>num[n]){puts("-1");continue;}
int l1,r1,l2,r2;
solve(l1,r1,a),solve(l2,r2,b);
ans=l1==l2?0x3f3f3f3f:A.query(l1,l2);
ans=min(ans,(ll)min(r1-l1+1,r2-l2+1));
sum+=ans*ans;
ans=r1==r2?0x3f3f3f3f:B.query(n-r1+1,n-r2+1);
ans=min(ans,(ll)min(r1-l1+1,r2-l2+1));
sum+=ans*ans;
cout<<sum<<'\n';
}
return 0;
}
2018.11.30 bzoj3230: 相似子串(后缀数组)的更多相关文章
- BZOJ3230 相似子串[后缀数组+二分+st表]
BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...
- [BZOJ3230]相似子串(后缀数组)
显然可以通过后缀数组快速找到询问的两个串分别是什么,然后正反各建一个后缀数组来求两个串的LCP和LCS即可. #include<cstdio> #include<cstring> ...
- 2018.11.24 poj3261Milk Patterns(后缀数组)
传送门 后缀数组经典题. 貌似可以用二分答案+后缀数组? 我自己yyyyyy了一个好写一点的方法. 直接先预处理出heightheightheight数组. 然后对于所有连续的k−1k-1k−1个he ...
- 2018.11.24 poj3415Common Substrings(后缀数组+单调栈)
传送门 常数实在压不下来(蒟蒻开O(3)都过不了). 但有正确性233. 首先肯定得把两个字符串接在一起. 相当于heightheightheight数组被height<kheight<k ...
- URAL 1297 最长回文子串(后缀数组)
1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...
- poj 2774 最长公共子串 后缀数组
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 25752 Accepted: 10 ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组
http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...
- Cogs 1709. [SPOJ705]不同的子串 后缀数组
题目:http://cojs.tk/cogs/problem/problem.php?pid=1709 1709. [SPOJ705]不同的子串 ★★ 输入文件:subst1.in 输出文件: ...
随机推荐
- Android 环境搭建与Android SDK目录介绍
Android SDK下载和安装 本地已有合适版本Android SDK,则无需再下载,或者可以使用SDK Manager更新SDK: 没有SDK,则需要下载. 这里说一下使用SDK Manager下 ...
- 203. Remove Linked List Elements (List)
Remove all elements from a linked list of integers that have value val. ExampleGiven: 1 --> 2 --& ...
- TZOJ 3659 神奇的探险之旅(有向无环每个点只能经过一次最长路dij)
描述 我们正在设计这样的一款儿童探险游戏:游戏由很多故事场景组成,每个场景中都有一个问题,游戏根据玩家的回答将进入下一场景,经过巧妙的设计,我们保证在一次“探险旅行”中,不会重复的进入任何相同的场景, ...
- Linux下打开超大文件方法
在Linux下用VIM打开大小几个G.甚至几十个G的文件时,是非常慢的. 这时,我们可以利用下面的方法分割文件,然后再打开. 1 查看文件的前多少行 head -10000 /var/lib/mysq ...
- docker-ce-17.09 容器创建,运行,进入,删除,导入/导出
docker容器是镜像运行的一个运行实例,带有额外的可写文件层. 一.创建容器 > docker create -it centos:latest create命令新建的容器处于停止状态,可以使 ...
- Vue 局部组件和全局组件的使用
<template> <div id="app"> <!--<img alt="Vue logo" src="./ ...
- JavaScript 练习题
练习题 1. 使用for循环输出1到50的值,要求每次循环只能输出一个值,每输出十个换一行. 2 日历生成器: 要求 用户输入,这个月有多少天,本月1号是星期几,自动生成日历 3. 表格生成器 4. ...
- PAT 1001 害死人不偿命的(3n+1)猜想 (15)(C++&JAVA&Python)
1001 害死人不偿命的(3n+1)猜想 (15)(15 分) 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反 ...
- 实用SQL大全
一.基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql server --- ...
- Luogu 1341 无序字母对 - 欧拉路径
Solution 找一条字典序最小的欧拉路径. 用 $multiset$ 存储领接表. 欧拉路径模板传送门 Code #include<cstdio> #include<cstrin ...