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. Eclipse工具的问题

    1 Eclipse采用ctrl抄 粘贴很卡 Eclipse -- Windows->Preferences->General->Editors->Text Editors-&g ...

  2. 如何将IPhone应用软件发布到App Store的

    转自:http://www.shtion.com/667.html 怎样将IPhone应用程序软件公布到应用程序商店? 2009年10月19日公布 分类: App store, iphone, 手机应 ...

  3. 在将 varchar 值 '2,7' 转换成数据类型 int 时失败

    消息 245,级别 16,状态 1,第 1 行在将 varchar 值 '2,7' 转换成数据类型 int 时失败. 原sql select  UserName from s_User  where ...

  4. Xamarin.Android 入门实例(1)之获取与解析JSON

    1.Main.axml 视图界面 2.视图代码 <?xml version="1.0" encoding="utf-8"?> <LinearL ...

  5. Java OCR tesseract 图像智能字符识别技术 Java代码实现

    接着上一篇OCR所说的,上一篇给大家介绍了tesseract 在命令行的简单用法,当然了要继承到我们的程序中,还是需要代码实现的,下面给大家分享下java实现的例子. 拿代码扫描上面的图片,然后输出结 ...

  6. DFA和trie特里实现敏感词过滤(python和c语言)

    今天的项目是与完成python开展,需要使用做关键词检查,筛选分类,使用前c语言做这种事情.有了线索,非常高效,内存小了,检查快. 到达python在,第一个想法是pip基于外观的c语言python特 ...

  7. 返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller

    原文:返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller [索引页][源码下载] 返璞归真 asp.net mvc (7) - asp.net ...

  8. Codeforces Round #234 (Div. 2) B. Inna and New Matrix of Candies

    B. Inna and New Matrix of Candies time limit per test 1 second memory limit per test 256 megabytes i ...

  9. 在SSMS里查看TDS数据包内容

    原文:在SSMS里查看TDS数据包内容 在SSMS里查看TDS数据包内容 摘抄自<SQLSERVER2012实施与管理实战指南> 要具体查看TDS数据库的内容,我们可以: 用NETWORK ...

  10. maple 教程

    1 初识计算机代数系统Maple 1.1 Maple简说 1980年9月, 加拿大Waterloo大学的符号计算机研究小组成立, 開始了符号计算在计算机上实现的研究项目, 数学软件Maple是这个项目 ...