HDOJ 5008 Boring String Problem
后缀数组+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
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
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)
the smallest l. If there is no l,r satisfied, output “0 0”. Note that s1...n is the whole string)
aaa
4
0
2
3
5
1 1
1 3
1 2
0 0
#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的更多相关文章
- 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 ...
- HDU 5008 Boring String Problem(后缀数组+二分)
题目链接 思路 想到了,但是木写对啊....代码 各种bug,写的乱死了.... 输出最靠前的,比较折腾... #include <cstdio> #include <cstring ...
- HDU 5008 Boring String Problem
题意:给定一个串长度<=1e5,将其所有的不同的字串按照字典序排序,然后q个询问,每次询问字典序第k小的的起始坐标,并且起始坐标尽量小. 分析: 一开始看错题意,没有意识到是求不同的字串中第k小 ...
- HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...
- HDU5008 Boring String Problem(后缀数组)
练习一下字符串,做一下这道题. 首先是关于一个字符串有多少不同子串的问题,串由小到大排起序来应该是按照sa[i]的顺序排出来的产生的. 好像abbacd,排序出来的后缀是这样的 1---abbacd ...
- HDU 3374 String Problem(KMP+最大/最小表示)
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu3374 String Problem【最小表示法】【exKMP】
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu3374 String Problem
地址:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题目: String Problem Time Limit: 2000/1000 MS (Java/ ...
- HDU3374 String Problem —— 最小最大表示法 + 循环节
题目链接:https://vjudge.net/problem/HDU-3374 String Problem Time Limit: 2000/1000 MS (Java/Others) Me ...
随机推荐
- 解决locate无法使用的问题
使用yum安装,locate的安装包名为mlocate 安装: yum -y install mlocate 更新: updatedb 无法使用:先下载
- Mysql优化之优化工具profiling
程序员的成长之路 2016-11-23 22:42 Mysql优化之优化工具profiling 前言 mysql优化技术: mysql优化不是做一个操作就可以的优化,它包含很多的细节,需要一点一点的优 ...
- 洛谷——P1351 联合权值
https://www.luogu.org/problem/show?pid=1351 题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i , ...
- ASP.net session丢失
ASP.NET Session的实现: asp.net的Session是基于HttpModule技术做的,HttpModule可以在请求被处理之前,对请求进行状态控制,由于Session本身就是用来做 ...
- 拿到offer过后--大学最后时光最想做的那十件事
昨天--2014.10.26,历史性的一刻,激动的签了欢聚时代(YY)的前端开发offer,工作地点是我喜欢的珠海(仅仅由于那边有我所向往的海还有自行车队,如今想想都乐开怀了,绕着海边骑单车的感觉真妙 ...
- cocos2d-x:读取指定文件夹下的文件名称+解决中文乱码(win32下有效)
援引:http://blog.csdn.net/zhanghefu/article/details/21284323 http://blog.csdn.net/cxf7394373/article/d ...
- linux 磁盘分区,主分区,扩展分区,逻辑分区以sata接口为例
以sata接口(依据linux内核检測其顺序 sda,sdb...)为例, 1, 硬盘的限制,最多仅仅能设置4个分区(主分区+扩展分区),路径例如以下, /dev/sda1 /dev/sda2 ...
- 深搜解Riding the Fences
Riding the Fences Farmer John owns a large number of fences that must be repairedannually. He traver ...
- accept-language
Chrome: [zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4]Safari: [zh-tw]FF: [zh-TW,zh;q=0.8,en-US;q=0.5,en;q=0.3 ...
- 用canvas画一个的小画板(PC端移动端都能用)
前言 本篇的内容主要包括: canvas标签简介 画板的功能简介 画板的JS部分(包括:1.获取画布 2.使画板全屏幕显示且自适应 3.如何绘制直线 4.绘画时的三种状态(鼠标点击.移动.离开)5.画 ...