spoj 7258

Lexicographical Substring Search

Time Limit:  1000MS Memory Limit:  Unknown 64bit IO Format:  %lld & %llu

Description

Little Daniel loves to play with strings! He always finds different ways to have fun with strings! Knowing that, his friend Kinan decided to test his skills so he gave him a string S  and asked him  Q  questions of the form:

If all distinct substrings of string  S  were sorted lexicographically, which one will be the  K-th  smallest?

After knowing the huge number of questions Kinan will ask, Daniel figured out that he can‘t do this alone. Daniel, of course, knows your exceptional programming skills, so he asked you to write him a program which given  S  will answer Kinan‘s questions.


Example:

S  = "aaa" (without quotes)

substrings of S are "a" , "a" , "a" , "aa" , "aa" , "aaa". The sorted list of substrings will be:

"a", "aa", "aaa".

Input

In the first line there is Kinan‘s string S
 (with length no more than 90000 characters). It contains only small
letters of English alphabet. The second line contains a single integer  Q  ( Q  <= 500) , the number of questions Daniel will be asked. In the next  Q  lines a single integer  K  is given (0 <  K  < 2^31).

Output

Output consists of Q  lines, the  i-th  contains a string which is the answer to the  i-th  asked question.

Example

Input:

aaa

2

2

3

Output:

aa

aaa

题目大意:

给出一个字符串以及若干个询问.

求出这个字符串中第K大的字符串.....

思路:

这个思路非常的明了..

先统计出字串的个数,然后按照BST的寻找第K大的方法去寻找就ok了....

常数卡得紧,就下次再优化吧....

  1 #include<cstdlib>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 typedef unsigned int uint;
  7 const int maxn = (int)1e5,sigma = 26;
  8 char str[maxn];
  9 int q;
 10 uint k;
 11 int cmp(int,int);
 12 struct Sam{
 13     int ch[maxn * 2][sigma],par[maxn * 2],stp[maxn * 2],id[maxn * 2],sub[maxn * 2];
 14     int sz,last;
 15     void init(){
 16         memset(ch,0,sizeof(ch)); memset(par,0,sizeof(par)); memset(stp,0,sizeof(stp));
 17         sz = last = 1;
 18     }
 19     void ext(int c){
 20         stp[++sz] = stp[last] + 1;
 21         int p = last, np = sz;
 22         for(; !ch[p][c]; p = par[p]) ch[p][c] = np;
 23         if(p == 0) par[np] = 1;
 24         else{
 25             int q = ch[p][c];
 26             if(stp[q] != stp[p] + 1){
 27                 stp[++sz] = stp[p] + 1;
 28                 int nq = sz;
 29                 memcpy(ch[nq],ch[q],sizeof(ch[q]));
 30                 par[nq] = par[q];
 31                 par[q] = par[np] = nq;
 32                 for(; ch[p][c] == q; p = par[p]) ch[p][c] = nq;
 33             }
 34             else
 35                 par[np] = q;
 36         }
 37         last = np;
 38     }
 39     void ins(char *pt){
 40         int i;
 41         init();
 42         for(i = 0; pt[i]; ++i) ext(pt[i] - ‘a‘);
 43     }
 44     void prep(){
 45         int i,j;
 46         for(i = 1; i <= sz; ++i) id[i] = i;
 47         sort(id + 1, id + sz + 1, cmp);
 48         for(i = 1; i <= sz; ++i) sub[i] = 1;
 49         for(i = 1; i <= sz; ++i)
 50             for(j = 0; j < sigma; ++j)
 51                 if(ch[id[i]][j]) sub[id[i]] += sub[ch[id[i]][j]];
 52     }
 53     void solve(uint k){
 54         int i,x = 1;
 55         while(k){
 56             for(i = 0; i < sigma; ++i)
 57                 if(ch[x][i] && k <= sub[ch[x][i]]){
 58                     printf("%c",i + ‘a‘);
 59                     x = ch[x][i];
 60                     k--;
 61                     break;
 62                 }
 63                 else k -= sub[ch[x][i]];
 64         }
 65         printf("\n");
 66     }
 67 }sam;
 68 int cmp(int x,int y){
 69     return sam.stp[x] > sam.stp[y];
 70 }
 71 int main()
 72 {
 73     freopen("sublex.in","r",stdin);
 74     freopen("sublex.out","w",stdout);
 75     scanf("%s",str);
 76     sam.ins(str);
 77     sam.prep();
 78     scanf("%d",&q);
 79     while(q--){
 80         scanf("%u",&k);
 81         sam.solve(k);
 82     }
 83     return 0;
 84 }
 85
 86 int cmp(int x,int y){
 87     return sam.stp[x] > sam.stp[y];
 88 }
 89 int main()
 90 {
 91     scanf("%s",str);
 92     sam.ins(str);
 93     sam.prep();
 94     scanf("%d",&q);
 95     while(q--){
 96         scanf("%u",&k);
 97         sam.solve(k);
 98     }
 99     return 0;
100 } 

时间: 2024-10-26 02:06:16

spoj 7258的相关文章

SPOJ 7258 Lexicographical Substring Search(后缀自动机)

[题目链接] http://www.spoj.com/problems/SUBLEX/ [题目大意] 给出一个字符串,求其字典序排名第k的子串 [题解] 求出sam上每个节点被经过的次数,然后采用权值线段树上查找第k大数类似的方法, 每次确定查找范围,进入相应的子树,同时输出路径上的点即可. [代码] #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const

spoj 7258 SUBLEX(求第k大字串

其实对sam的拓扑排序我似懂非懂但是会用一点了. /** @xigua */ #include <stdio.h> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <cstring> #include <queue> #include <set>

后缀自动机(SAM)学习指南

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.

后缀自己主动机(SAM)学习指南

*在学习后缀自己主动机之前须要熟练掌握WA自己主动机.RE自己主动机与TLE自己主动机* 什么是后缀自己主动机 后缀自己主动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造.可以接受一个字符串全部后缀的自己主动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 能够用 SAM 轻松水过.由此 SAM 流行了起来. 一般来说.能用后缀自己主动机解决的问题都能够用后缀数组解决.可是后缀自己

后缀自动机(SAM)

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.

后缀自动机详解 -----转载

转载于:http://blog.csdn.net/qq_35649707/article/details/66473069 原论文(俄文)地址:suffix_automata 后缀自动机 后缀自动机(单词的有向无环图)——是一种强有力的数据结构,让你能够解决许多字符串问题. 例如,使用后缀自动机可以在某一字符串中搜索另一字符串的所有出现位置,或者计算不同子串的个数——这都能在线性 时间内解决. 直觉上,后缀自动机可以被理解为所有子串的简明信息.一个重要的事实是,后缀自动机以压缩后的形式包含了一个

后缀自动机练习专题

后缀自动机练习专题 一些比较有用的东东: (1) \(\text{sam}\) 上一条从初始状态出发的路径对应一个子串 (2) \(\text{parent}\) 树上一个节点能表示的最长的串对应一个前缀/后缀 (3) \(len(u)\) 表示节点 \(u\) 能表示的最长串的长度 (4) \(fa(u)\) 表示节点 \(u\) 的后缀链接指向的节点,也就是其在 \(\text{parent}\) 树上的父亲 (5) 表示两个后缀的公共前缀的节点是两个后缀在 \(\text{parent}\

SPOJ SUBLEX 7258. Lexicographical Substring Search

看起来像是普通的SAM+dfs...但SPOJ太慢了......倒腾了一个晚上不是WA 就是RE ..... 最后换SA写了...... Lexicographical Substring Search Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   [Go Back]   [Status] Description Little Daniel loves to play wi

【SPOJ】7258. Lexicographical Substring Search(后缀自动机)

http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一个子串,而且不重复.(原因似乎是逆序后缀树? 所以我们在自动机上预处理每一个状态的子串数目,然后从小到大枚举字符. 子串数目可以这样预处理出:s[x]=sum{s[y]}+1, y是x出发的下一个点,意思就是说,以x开头的子串有那么多个(即将孩子的所有子串前边都加上x),然后x单独算一个子串. 然后