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
 

题意:求第k大的子串,输出左右端点,且左端点尽量小。

思路:首先。我们能够计算出不同的子串个数,这个在论文里有的。就是

n-sa[i]-height[i]。

然后我们就能够统计第i大的字符串有的子串个数,然后二分查找到第k个所在的第sa[i]后缀,接着我们能够先确定右端点的范围来RMQ查找sa[j]最小的那个。仅仅要是满足和sa[i]后缀的lcp的长度大于len,就代表也包括这个子串了,接着就是RMQ了,坑点就是l=mid的时候的多一个推断

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
//typedef long long ll;
typedef __int64 ll;
using namespace std;
const int maxn = 100010; int sa[maxn];
int t1[maxn], t2[maxn], c[maxn];
int rank[maxn], height[maxn]; void build_sa(int s[], int n, int m) {
int i, j, p, *x = t1, *y = t2;
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[x[i] = s[i]]++;
for (i = 1; i < m; i++) c[i] += c[i-1];
for (i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for (j = 1; j <= n; j <<= 1) {
p = 0;
for (i = n-j; i < n; i++) y[p++] = i;
for (i = 0; i < n; i++)
if (sa[i] >= j)
y[p++] = sa[i] - j;
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[x[y[i]]]++;
for (i = 1; i < m; i++) c[i] += c[i-1];
for (i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y);
p = 1, x[sa[0]] = 0;
for (i = 1; i < n; i++)
x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p-1 : p++; if (p >= n) break;
m = p;
}
} void getHeight(int s[],int n) {
int i, j, k = 0;
for (i = 0; i <= n; i++)
rank[sa[i]] = i; for (i = 0; i < n; i++) {
if (k) k--;
j = sa[rank[i]-1];
while (s[i+k] == s[j+k]) k++;
height[rank[i]] = k;
}
}
int dp[maxn][30];
char str[maxn];
int r[maxn], ind[maxn][30];
ll b[maxn]; void initRMQ(int n) {
int m = floor(log(n+0.0) / log(2.0));
for (int i = 1; i <= n; i++)
dp[i][0] = height[i]; for (int i = 1; i <= m; i++) {
for (int j = n; j; j--) {
dp[j][i] = dp[j][i-1];
if (j+(1<<(i-1)) <= n)
dp[j][i] = min(dp[j][i], dp[j+(1<<(i-1))][i-1]);
}
}
} int lcp(int l, int r) {
int a = rank[l], b = rank[r];
if (a > b)
swap(a,b);
a++;
int m = floor(log(b-a+1.0) / log(2.0));
return min(dp[a][m], dp[b-(1<<m)+1][m]);
} void init(int n) {
int m = floor(log(n+0.0) / log(2.0));
for (int i = 1; i <= n; i++)
ind[i][0] = sa[i]; for (int i = 1; i <= m; i++) {
for (int j = n; j; j--) {
ind[j][i] = ind[j][i-1];
if (j+(1<<(i-1)) <= n)
ind[j][i] = min(ind[j][i], ind[j+(1<<(i-1))][i-1]);
}
}
} int rmq(int a, int b) {
int m = floor(log(b-a+1.0) / log(2.0));
return min(ind[a][m], ind[b-(1<<m)+1][m]);
} int main() {
while (scanf("%s", str) != EOF) {
int n = strlen(str);
for (int i = 0; i <= n; i++)
r[i] = str[i];
build_sa(r, n+1, 128);
getHeight(r, n);
initRMQ(n);
init(n); b[0] = 0;
for (int i = 1; i <= n; i++)
b[i] = b[i-1] + n - sa[i] - height[i]; int m;
scanf("%d", &m);
ll k;
int lastl = 0, lastr = 0;
while (m--) {
scanf("%I64d", &k);
k = (k ^ lastl ^ lastr) + 1;
if (k > b[n]) {
printf("0 0\n");
lastl = 0;
lastr = 0;
continue;
}
int id = lower_bound(b+1, b+1+n, k) - b;
k -= b[id-1];
int len = height[id] + k;
int ll = id;
int rr = id;
int L = id, R = n;
while (L <= R) {
int mid = (L + R) / 2;
if (sa[id] == sa[mid] || lcp(sa[id], sa[mid]) >= len) {
rr = mid;
L = mid + 1;
}
else R = mid - 1;
} int ansl = rmq(ll, rr) + 1;
int ansr = ansl + len - 1;
printf("%d %d\n", ansl, ansr);
lastl = ansl;
lastr = ansr;
}
}
return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

HDU - 5008 Boring String Problem (后缀数组+二分法+RMQ)的更多相关文章

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

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

  2. HDU 5008 Boring String Problem

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

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

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

  4. HDOJ 5008 Boring String Problem

    后缀数组+RMQ+二分 后缀数组二分确定第K不同子串的位置 , 二分LCP确定可选的区间范围 , RMQ求范围内最小的sa Boring String Problem Time Limit: 6000 ...

  5. HDU 3518 Boring counting(后缀数组,字符处理)

    题目 参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html 题目描述: 找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠). ...

  6. poj 1743 Musical Theme (后缀数组+二分法)

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16162   Accepted: 5577 De ...

  7. 【bzoj5073】[Lydsy1710月赛]小A的咒语 后缀数组+倍增RMQ+贪心+dp

    题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ...

  8. 【bzoj3879】SvT 后缀数组+倍增RMQ+单调栈

    题目描述 (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示), ...

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

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

随机推荐

  1. windows azure Vm、cloud service、web application 如何选择可用的服务

    windows azure 的web应用和虚拟机都经常用.我们经常把我们的网站部署上去.一般选择web应用或者开一个虚拟机.开一个虚拟机就会按照虚拟机的使用时间进行计费. 那么我们选择web部署在哪里 ...

  2. 【原创】UVAOJ水题10025解题报告

    首先是原题,转自UVAOJ  The ? 1 ? 2 ? ... ? n = k problem  The problem Given the following formula, one can s ...

  3. js匀速运动停止条件

    匀速运动,怎么让它到达指定位置时停止呢? 原理: 1,物体和目标的差值距离小于等于速度时,即停止 2,接着让物体移动位置等于目标位置 示例:匀速运动停止 html部分 <input type=& ...

  4. android传感器;摇抽奖功能

    package com.kane.sensortest; import java.util.Random; import android.hardware.Sensor; import android ...

  5. eclipse报错:发现了以元素 'd:skin' 开头的无效内容。此处不应含有子元素

    Console报错: sdk\system-images\android-22\android-wear\armeabi-v7a\devices.xml cvc-complex-type.2.4.d: ...

  6. 构建安全的Xml Web Service系列之wse之错误代码详解

    原文:构建安全的Xml Web Service系列之wse之错误代码详解 WSE3.0现在还没有中文版的可以下载,使用英文版的过程中,难免会遇到各种各样的错误,而面对一堆毫无头绪的错误异常,常常会感到 ...

  7. Cocos2d-x 如何输出 Android用电话 腰带Tag的Log刊物

    于Cocos2d-x根据代码 #if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) #define LOGAnroid( ...) #else if (CC_TAR ...

  8. 如何ios中间Safari在开发了类似的native app像全屏webapp

    本文交换了我www.gbtags.com文章. <meta name="format-detection" content="telephone=no email= ...

  9. Sql中联合查询中的”子查询返回的值不止一个“的问题

    在子查询中,如果想实现如下的功能: select lib,count(*),select sum(newsNo) from Table1 group by lib from Tabel1 T1,Tab ...

  10. 基于docker构建jenkins和svn服务(转)

    码农们很定都知道svn的重要性,机器坏掉丢代码的惨痛教训想必很多人都有. jenkins可能很多人都不了解.这是一个持续集成的工具,在敏捷开发领域很流行:跟svn结合可以实现定期build.check ...