3230: 相似子串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 913  Solved: 223
[Submit][Status]
Description

Input

输入第1行,包含3个整数N,Q。Q代表询问组数。
第2行是字符串S。
接下来Q行,每行两个整数i和j。(1≤i≤j)。

Output

输出共Q行,每行一个数表示每组询问的答案。如果不存在第i个子串或第j个子串,则输出-1。

Sample Input

5 3

ababa

3 5

5 9

8 10

Sample Output

18

16

-1

HINT

样例解释

第1组询问:两个子串是“aba”,“ababa”。f = 32 + 32 = 18。

第2组询问:两个子串是“ababa”,“baba”。f = 02 + 42 = 16。

第3组询问:不存在第10个子串。输出-1。

数据范围

N≤100000,Q≤100000,字符串只由小写字母'a'~'z'组成

Source

后缀数组+二分+RMQ

题解:

字典序第i?我们给每个排名为i后缀i一个ed[i]表示截止到排名i,一共有多少个本质不同的子串,然后在ed数组上lower_bound就可以找到子串的左端点,然后就知道右端点了。

然后求LCP?和LCS?(longest common suffix?)

两个后缀数组可以O(nlogn)预处理,O(1)查询。

hash可以O(n)预处理,O(logn)查询。

作为蒟蒻我写了后一种。。。

代码:

 #include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 150000+5
#define maxm 500+100
#define eps 1e-10
#define ll long long
#define ull unsigned long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
#define base 13131
using namespace std;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
int n,q,s[maxn],t[maxn],t2[maxn],c[maxn],sa[maxn],rk[maxn],h[maxn];
ll ed[maxn];
ull hash[maxn],mi[maxn];
void getsa(int m)
{
int *x=t,*y=t2;
for0(i,m)c[i]=;
for0(i,n)c[x[i]=s[i]]++;
for1(i,m)c[i]+=c[i-];
for3(i,n,)sa[--c[x[i]]]=i;
for(int k=;k<=n+;k<<=)
{
int p=;
for2(i,n-k+,n)y[p++]=i;
for0(i,n)if(sa[i]>=k)y[p++]=sa[i]-k;
for0(i,m)c[i]=;
for0(i,n)c[x[y[i]]]++;
for1(i,m)c[i]+=c[i-];
for3(i,n,)sa[--c[x[y[i]]]]=y[i];
swap(x,y);p=;x[sa[]]=;
for1(i,n)x[sa[i]]=y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k]?p:++p;
if(p>=n)break;
m=p;
}
for1(i,n)rk[sa[i]]=i;
for(int i=,k=,j;i<n;h[rk[i++]]=k)
for(k?k--:,j=sa[rk[i]-];s[i+k]==s[j+k];k++);
}
void gethash()
{
mi[]=;
for1(i,n)mi[i]=mi[i-]*(ull)base;
for3(i,n-,)hash[i]=hash[i+]*(ull)base+s[i];
}
inline ull get(int x,int y){return hash[x]-hash[x+y]*mi[y];}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();q=read();
for0(i,n-){char ch=getchar();while(ch<'a'||ch>'z')ch=getchar();s[i]=ch-'a'+;}
s[n]=;
getsa();
for1(i,n)ed[i]=n-sa[i]-h[i];
for1(i,n)ed[i]+=ed[i-];
gethash();
while(q--)
{
ll x=read(),y=read();
if(x<||y<||x>ed[n]||y>ed[n]){printf("-1\n");continue;}
ll t=lower_bound(ed+,ed+n+,x)-ed,l1=sa[t],r1=sa[t]+h[t]+x-ed[t-]-;
t=lower_bound(ed+,ed+n+,y)-ed;ll l2=sa[t],r2=sa[t]+h[t]+y-ed[t-]-;
int l=,r=min(r1-l1+,r2-l2+);
while(l<=r)
{
int mid=(l+r)>>;
if(get(l1,mid)==get(l2,mid))l=mid+;else r=mid-;
}
ll ans=(ll)r*(ll)r;
l=,r=min(r1-l1+,r2-l2+);
while(l<=r)
{
int mid=(l+r)>>;
if(get(r1-mid+,mid)==get(r2-mid+,mid))l=mid+;else r=mid-;
}
ans+=(ll)r*(ll)r;
printf("%lld\n",ans);
}
return ;
}

BZOJ3230: 相似子串的更多相关文章

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

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

  2. BZOJ3230 相似子串 字符串 SA ST表

    原文链接http://www.cnblogs.com/zhouzhendong/p/9033092.html 题目传送门 - BZOJ3230 题意 给定字符串$s$.长度为$n$. 现在有$Q$组询 ...

  3. BZOJ3230 相似子串 【后缀数组】

    题目分析: 容易想到sa排好序之后,子串排名就是前面的子串减去height数组.所以正着做一遍,倒着做一遍就行了. 代码: #include<bits/stdc++.h> using na ...

  4. BZOJ3230: 相似子串【后缀数组】

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

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

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

  6. 2018.11.30 bzoj3230: 相似子串(后缀数组)

    传送门 后缀数组入门题. 建立正反两个后缀数组算就行了. 代码: #include<bits/stdc++.h> #define ri register int using namespa ...

  7. bzoj3796(后缀数组)(SA四连)

    bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...

  8. 【bzoj3230】相似子串

    Portal -->bzoj3230 Description 给你一个长度为\(n\)的字符串,把它的所有本质不同的子串按字典序大小排序,有\(m\)个询问,对于每一个询问\(x,y\)你需要回 ...

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

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

随机推荐

  1. android 电话拨号器

    电话拨号器(重点)            1.产品经理: 需求分析文档,设计原型图    2.UI工程师: 设计UI界面    3.架构师: 写架构,接口文档    4.码农: 服务端,客户端     ...

  2. Python快速入门学习笔记(一)

    本篇文章适合有其他高级语言基础的人群阅读 使用的Python版本为python2.7 使用的编辑器为Sublime Text3 世界始于Hello World: print 'Hello world' ...

  3. [DP] LGTB 玩THD (复杂状态DP)

    LGTB 玩THD LGTB 最近在玩一个类似DOTA 的游戏名叫THD有一天他在守一座塔,对面的N 个小兵排成一列从近到远站在塔前面每个小兵有一定的血量hi,杀死后有一定的金钱gi每一秒,他都可以攻 ...

  4. Java_log4j

      Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.事件记录器等:我们也可以控制每一条日志的输出格式: ...

  5. PHP递归

    <?php /** * Mr.xml * 处理无限级分类 */ class Category{ /** * [递归一维数组] * @param [type] $cate [传递一个数组$cate ...

  6. memcached完全剖析--1

    memcached的基础 翻译一篇技术评论社的文章,是讲memcached的连载.fcicq同学说这个东西很有用,希望大家喜欢. 发表日:2008/7/2 作者:长野雅广(Masahiro Nagan ...

  7. apache开启gzip的方法

    在Apache中开启gzip压缩方法为: 1. 在httpd.conf 或者博客根目录的.htaccess文件中加入如下规则(Apache服务器需要支持 mod_deflate) 本文出处参考:htt ...

  8. Socket 入门

    int socket(int domain, int type,int protocol) domain :说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等). AF_UNI ...

  9. 数位DP入门之hdu 3555 Bomb

    hdu 3555 Bomb 题意: 在1~N(1<=N<=2^63-1)范围内找出含有 ‘49’的数的个数: 与hdu 2089 不要62的区别:2089是找不不含 '4'和 '62'的区 ...

  10. 【重构】m站重构思路

    不重构全部模块,只对以下内容做基础重构就可以,第三方方式 1.验证码作为独立的服务,用户写入验证码获得id,服务端获取验证码id对应内容(根据时间和存储空间 清理验证码) 2.支付接口h5环境独立配置 ...