后缀数组+RMQ+二分

后缀数组二分确定第K不同子串的位置 , 二分LCP确定可选的区间范围 , RMQ求范围内最小的sa

Boring String Problem

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 661    Accepted Submission(s): 183

Problem Description
In this problem, you are given a string s and q queries.



For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is the k-th smallest. 



A substring si...j of the string s = a1a2 ...an(1 ≤ i ≤ j ≤ n) is the string aiai+1 ...aj. Two substrings sx...y and sz...w are cosidered to be distinct if sx...y ≠
Sz...w
 
Input
The input consists of multiple test cases.Please process till EOF. 



Each test case begins with a line containing a string s(|s| ≤ 105) with only lowercase letters.



Next line contains a postive integer q(1 ≤ q ≤ 105), the number of questions.



q queries are given in the next q lines. Every line contains an integer v. You should calculate the k by k = (l⊕r⊕v)+1(l, r is the output of previous question, at the beginning of each case l = r = 0, 0 < k < 263, “⊕” denotes exclusive or)
 
Output
For each test case, output consists of q lines, the i-th line contains two integers l, r which is the answer to the i-th query. (The answer l,r satisfies that sl...r is the k-th smallest and if there are several l,r available, ouput l,r which with
the smallest l. If there is no l,r satisfied, output “0 0”. Note that s1...n is the whole string)
 
Sample Input
aaa
4
0
2
3
5
 
Sample Output
1 1
1 3
1 2
0 0
 
Source
 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; typedef long long int LL; const int maxn=110100;
const int INF=0x3f3f3f3f; int sa[maxn],rank[maxn],rank2[maxn],h[maxn],c[maxn],
*x,*y,ans[maxn];
char str[maxn]; bool cmp(int* r,int a,int b,int l,int n)
{
if(r[a]==r[b]&&a+l<n&&b+l<n&&r[a+l]==r[b+l])
return true;
return false;
} void radix_sort(int n,int sz)
{
for(int i=0;i<sz;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[y[i]]]++;
for(int i=1;i<sz;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
} void get_sa(char c[],int n,int sz=128)
{
x=rank,y=rank2;
for(int i=0;i<n;i++) x[i]=c[i],y[i]=i;
radix_sort(n,sz);
for(int len=1;len<n;len<<=1)
{
int yid=0;
for(int i=n-len;i<n;i++) y[yid++]=i;
for(int i=0;i<n;i++) if(sa[i]>=len) y[yid++]=sa[i]-len; radix_sort(n,sz); swap(x,y);
x[sa[0]]=yid=0; for(int i=1;i<n;i++)
{
x[sa[i]]=cmp(y,sa[i],sa[i-1],len,n)?yid:++yid;
}
sz=yid+1;
if(sz>=n) break;
}
for(int i=0;i<n;i++) rank[i]=x[i];
} void get_h(char str[],int n)
{
int k=0; h[0]=0;
for(int i=0;i<n;i++)
{
if(rank[i]==0) continue;
k=max(k-1,0);
int j=sa[rank[i]-1];
while(i+k<n&&j+k<n&&str[i+k]==str[j+k]) k++;
h[rank[i]]=k;
}
} LL Range[maxn]; int bin(LL x,int n)
{
int ans=-1;
int low=0,high=n-1,mid;
while(low<=high)
{
mid=(low+high)/2;
if(Range[mid]<x)
{
ans=mid;
low=mid+1;
}
else
{
high=mid-1;
}
}
return ans;
} int lcp[maxn][20],mmm[maxn][20]; void RMQ_init(int n)
{
for(int i=0;i<n;i++)
{
lcp[i][0]=h[i];
mmm[i][0]=sa[i];
}
lcp[0][0]=0x3f3f3f3f;
int sz=floor(log(n*1.0)/log(2.0));
for(int i=1;(1<<i)<=n;i++)
{
for(int j=0;j+(1<<i)-1<n;j++)
{
lcp[j][i]=min(lcp[j][i-1],lcp[j+(1<<(i-1))][i-1]);
mmm[j][i]=min(mmm[j][i-1],mmm[j+(1<<(i-1))][i-1]);
}
}
} int LCP(int l,int r,int n)
{
if(l==r) return n-sa[l];
l++;
if(l>r) swap(l,r);
int k=0;
while(1<<(k+1)<=r-l+1) k++;
return min(lcp[l][k],lcp[r-(1<<k)+1][k]);
} int MMM(int l,int r)
{
if(l>r) swap(l,r);
int k=0;
while(1<<(k+1)<=r-l+1) k++;
return min(mmm[l][k],mmm[r-(1<<k)+1][k]);
} int binID(int x,int n,int len)
{
int ans=x;
int low=x,high=n-1,mid;
while(low<=high)
{
mid=(low+high)/2;
if(LCP(x,mid,n)>=len)
{
ans=mid;
low=mid+1;
}
else high=mid-1;
}
return ans;
}
int main()
{
while(scanf("%s",str)!=EOF)
{
int n=strlen(str);
get_sa(str,n);
get_h(str,n);
RMQ_init(n);
for(int i=0;i<n;i++)
{
Range[i]=(n-sa[i])-h[i];
if(i-1>=0) Range[i]+=Range[i-1];
}
int q;
scanf("%d",&q);
int L=0,R=0;
LL V;
while(q--)
{
scanf("%I64d",&V);
LL K=(L^R^V)+1LL;
if(K>Range[n-1])
{
L=0;R=0;
printf("%d %d\n",L,R);
continue;
}
int id=bin(K,n);
LL jian=0;
if(id>=0) jian=Range[id];
LL res=K-jian; id++;
int len=h[id]+res;
int hid=binID(id,n,len);
int Left=MMM(id,hid);
printf("%d %d\n",Left+1,Left+len);
L=Left+1;R=Left+len;
}
}
return 0;
}

HDOJ 5008 Boring String Problem的更多相关文章

  1. HDU - 5008 Boring String Problem (后缀数组+二分法+RMQ)

    Problem Description In this problem, you are given a string s and q queries. For each query, you sho ...

  2. HDU 5008 Boring String Problem(后缀数组+二分)

    题目链接 思路 想到了,但是木写对啊....代码 各种bug,写的乱死了.... 输出最靠前的,比较折腾... #include <cstdio> #include <cstring ...

  3. HDU 5008 Boring String Problem

    题意:给定一个串长度<=1e5,将其所有的不同的字串按照字典序排序,然后q个询问,每次询问字典序第k小的的起始坐标,并且起始坐标尽量小. 分析: 一开始看错题意,没有意识到是求不同的字串中第k小 ...

  4. HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...

  5. HDU5008 Boring String Problem(后缀数组)

    练习一下字符串,做一下这道题. 首先是关于一个字符串有多少不同子串的问题,串由小到大排起序来应该是按照sa[i]的顺序排出来的产生的. 好像abbacd,排序出来的后缀是这样的 1---abbacd ...

  6. HDU 3374 String Problem(KMP+最大/最小表示)

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  7. hdu3374 String Problem【最小表示法】【exKMP】

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  8. hdu3374 String Problem

    地址:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题目: String Problem Time Limit: 2000/1000 MS (Java/ ...

  9. HDU3374 String Problem —— 最小最大表示法 + 循环节

    题目链接:https://vjudge.net/problem/HDU-3374 String Problem Time Limit: 2000/1000 MS (Java/Others)    Me ...

随机推荐

  1. 设置PATH 环境变量、pyw格式、命令行运行python程序与多重剪贴板

    pyw格式简介: 与py类似,我认为他们俩卫衣的不同就是前者运行时候不显示终端窗口,后者显示 命令行运行python程序: 在我学习python的过程中我通常使用IDLE来运行程序,这一步骤太过繁琐( ...

  2. crm 系统项目(一) 登录,注册,校验

    crm 系统项目(一) 登录,注册,校验 首先创建一个Django项目,关于配置信息不多说,前面有~ models.py文件下创建需要的表格信息,之后导入数据库 from django.db impo ...

  3. iText、poi操作word2007(读取,生成)

    关于生成word文件以及插入文字.表格.图片等功能,我使用了poi和itext,因为poi插入图片的jar包我在网上查并不是太完全,也可能我没找到如何使用,所以插入图片我用的是itext iText所 ...

  4. java拷贝字符文件

    1.java拷贝字符文件 2.代码如下: package Demo1; import java.io.*; public class copyfile { public static void mai ...

  5. Ubuntu 15.10 安装Qt5.5.1

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50300447 本人使用的ubuntu系 ...

  6. 极路由4pro安装java(Jamvm 2.0.0 + gnu classpath 0.9.8)

    首先试了gnu classpath 0.9.9,编译不过后来改成0.9.8 编译环境 OS: 64位 Ubuntu 16.04 LTS(vmware虚拟机) SDK: 用之前讲过的官方SDKmtmip ...

  7. shell脚本学习之ubuntu删除多余内核

    #!/bin/bash #定期删除内核 #存储命令输出cmd_output=`commands` uname_output=$(uname -r) kernel_output=`dpkg --list ...

  8. fastjson 的简单使用

    public static void main(String[] args) { /*普通对象与json相互转换*/ User u = new User("miquan", &qu ...

  9. c++变量的作用域、生存期和可见性

    局部变量 范围:在一个函数内部定义的变量,作用范围仅仅限于本函数体内. 生存期:程序运行到本函数才会给局部变量分配内存单元.函数运行完成局部变量所占的存储单元就被释放 全局变量 在函数体外部定义的变量 ...

  10. jQuery Mobile(jqm)button的隐藏和显示,包含a标签,圆角和非圆角button

    在移动互联网时代,HTML5开发越来越收到欢迎. 于是各种HTML5的框架都出来了.因为对于jquery的熟悉,jquery mobile 为多数人选择学习的对象.我也是众多追求者之中的一个.近期一直 ...