传送门

后缀数组入门题。

建立正反两个后缀数组算就行了。

代码:

#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: 相似子串(后缀数组)的更多相关文章

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

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

  2. [BZOJ3230]相似子串(后缀数组)

    显然可以通过后缀数组快速找到询问的两个串分别是什么,然后正反各建一个后缀数组来求两个串的LCP和LCS即可. #include<cstdio> #include<cstring> ...

  3. 2018.11.24 poj3261Milk Patterns(后缀数组)

    传送门 后缀数组经典题. 貌似可以用二分答案+后缀数组? 我自己yyyyyy了一个好写一点的方法. 直接先预处理出heightheightheight数组. 然后对于所有连续的k−1k-1k−1个he ...

  4. 2018.11.24 poj3415Common Substrings(后缀数组+单调栈)

    传送门 常数实在压不下来(蒟蒻开O(3)都过不了). 但有正确性233. 首先肯定得把两个字符串接在一起. 相当于heightheightheight数组被height<kheight<k ...

  5. URAL 1297 最长回文子串(后缀数组)

    1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...

  6. poj 2774 最长公共子串 后缀数组

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25752   Accepted: 10 ...

  7. poj 1743 Musical Theme(最长重复子串 后缀数组)

    poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...

  8. 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组

    http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...

  9. Cogs 1709. [SPOJ705]不同的子串 后缀数组

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1709 1709. [SPOJ705]不同的子串 ★★   输入文件:subst1.in   输出文件: ...

随机推荐

  1. tcp中的keepalive(转)

    理解Keepalive(1) 大家都听过keepalive,但是其实对于keepalive这个词还是很晦涩的,至少我一直都只知道一个大概,直到之前排查线上一些问题,发现keepalive还是有很多玄机 ...

  2. [ERR] Node 192.168.25.135:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

    原文链接:https://www.cnblogs.com/huxinga/p/6644226.html 解决办法:将redis全部shutdown 将每个节点下aof.rdb.nodes.conf本地 ...

  3. mysql中left join设置条件在on与where时的区别

    一.首先我们准备两张表来进行测试. CREATE TABLE `a` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `na ...

  4. sqlserver打开对象资源管理器管理的帮助文档的快捷键

    sqlserver打开对象资源管理器管理的帮助文档的快捷键:Fn+F1

  5. C#执行javascript代码,执行复杂的javascript代码新方式

    1. 使用nuget 包"Jurassic", 注意,如果 nuget上的包 用起来出现错误,请自行下载 github代码,自行编译最新代码成dll,再引用. 官方的nuget包 ...

  6. An enumerable sequence of parameters (arrays, lists, etc) is not allo

    环境:dapper asp.net core 出错代码如下: public Task<IEnumerable<dynamic>> GetList(string query, p ...

  7. 如何查看mysql数据库表所使用的引擎(转载)

    我们怎么样才能准确的查看mysql的存储引擎呢,下面我给大家介绍两种正确的方式. 1)正确方式一: SHOW TABLE STATUS from 数据库库名 where Name='表名' 2)mys ...

  8. Fiddler抓包使用教程-安装配置

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72876628 本文出自[赵彦军的博客] Fiddler是什么? Fiddler是一 ...

  9. Linux CentOS 7 & JDK 1.7 安装与配置

    前言 简单记录一下在CentOS 7中安装配置JDK 1.7的全过程~ 下载 首先是jdk 1.7 64bit & 32bit的下载地址: jdk-7u79-linux-x64.tar.gz ...

  10. Andriod——手机尺寸相关的概念 +尺寸单位+关于颜色

    手机的尺寸: 屏幕对角线的长度,单位为英寸(2.54cm) 手机的分辨率: 屏幕能显示的像素的数量, 一般用在长方向上数量*宽方向上数量来表达 手机的像素密度: pixels per inch,也称P ...