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. Android系统开发(2)——GDB调试工具

    调试的过程 我们在eclipse中来看一下一般调试的过程: 1.debug模式编译 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGF3YW5nYW5iY ...

  2. 将DataTable 数据插入 SQL SERVER 数据库

    原文:将DataTable 数据插入 SQL SERVER 数据库 以下提供3中方式将DataTable中的数据插入到SQL SERVER 数据库: 一:使用sqlcommand.executenon ...

  3. Android更改checkbox的style

    resouce文件夹下,value文件夹下,styles.xml文件中新增样式: <resources> <style name="radioButton"> ...

  4. [LeetCode61]Rotate List

    题目: Given a list, rotate the list to the right by k places, where k is non-negative. For example:Giv ...

  5. Excel一项研究指出色彩

    Excel一项研究指出色彩 从Office2007跳到了2013版本号,尽管有着种种不适,但应该承认Excel2013版本号在图表和色彩上更加人性化和"专业"了一些. 但假设须要更 ...

  6. Project_2007关键

    本人今天成功用这个密钥,安装project2007. 分享给着急的小伙伴们. W2JJW-4KYDP-2YMKW-FX36H-QYVD8 版权声明:本文博客原创文章.博客,未经同意,不得转载.

  7. ym——Android之ListView性能优化

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! Android之ListView性能优化 假设有看过我写过的15k面试题的朋友们一定知 ...

  8. Android系统APN配置具体解释

     Android 系统APN配置具体解释 这些天一直在调系统原生的Settings.apk里面APN配置的问题.在设置里面手动添加了APN配置选项.可是在界面上还是看不到.所以跟了下代码.原以为就是简 ...

  9. Android studio 中国的垃圾问题解决

    为了获得良好的刚安装Android studio, 实例importproject时刻,你会发现很多中国的文件夹显示异常.例如下面的附图: 为什么会出现这个问题呢,事实上原因非常easy,由于Andr ...

  10. Android 通过应用程序来设置系统的日期和时间中的

    Android 通过应用程序来设置系统的日期和时间中的 android 2.3 android 4.0 测试可行,刚需ROOT权限. import java.io.DataOutputStream; ...