D - Lexicographical Substring Search

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:aaa223

Output:
aaaaa

Edited: Some input file contains garbage at the end. Do not process them.





让你求按字典序排名第k名的字符串是什么

dp处理出每个点往下走能够走出多少个串。
f[i]=sigma(f[ch[i][c])+1
这个可以按Max排序之后倒着推就好了。
询问的时候看一下走下去个数是否<=k,是的话就走下去,然后–k;否则就找下一条边。



 1 #include"bits/stdc++.h"
 2 using namespace std;
 3 const int N = 101000;
 4 #define int long long
 5 struct node
 6 {
 7     int fa;
 8     int ch[26];
 9     int len;
10 }dian[N<<1];
11 int cnt[N<<1];
12 int f[N<<1];
13 int last=1;int tot=1;
14
15 inline void add(int c)
16 {
17   int p=last; int np=last=++tot;
18   dian[np].len=dian[p].len+1;
19   for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np;
20   if(!p) dian[np].fa=1,cnt[1]++;
21   else
22   {
23      int q=dian[p].ch[c];
24      if(dian[q].len == dian[p].len+1)dian[np].fa=q,cnt[q]++;
25      else
26      {
27          int nq=++tot;
28          dian[nq]=dian[q];
29          dian[nq].len=dian[p].len+1;
30          dian[q].fa=dian[np].fa=nq;
31 ;         cnt[nq]+=2;
32          for(;p&&dian[p].ch[c] == q;p=dian[p].fa)dian[p].ch[c]=nq;
33      }
34   }
35 }
36
37
38 void dfs(int x)
39 {
40     if(f[x]) return ;
41     f[x]=1;
42     for(int i=0;i<26;i++)
43       {
44            if(dian[x].ch[i])
45            {dfs(dian[x].ch[i]);
46             f[x]+= f[dian[x].ch[i]];
47
48            }
49       }
50 }
51 void que()
52 {
53     int x;cin>>x; int now=1;
54     while(x)
55     {
56         for(int i=0;i<26;i++)if(dian[now].ch[i])
57         {
58             if(f[dian[now].ch[i]]>=x)
59             {
60                 putchar(‘a‘+i); --x;now=dian[now].ch[i];
61                 break;
62             }
63             else x-=f[dian[now].ch[i]];
64         }
65     }
66     cout<<‘\n‘;
67 }
68 signed main()
69 {
70     //  freopen("datte.txt","r",stdin);
71    //freopen("my.out","w",stdout);
72    string s;cin>>s; int len =s.length();
73     for(int i=0;i<len;i++)add(s[i]-‘a‘);
74
75     dfs(1);  int m;cin>>m;
76     while(m--)que();
77 }

原文地址:https://www.cnblogs.com/zhangbuang/p/10872357.html

时间: 2024-11-04 16:13:17

D - Lexicographical Substring Search的相关文章

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 SUBLEX - Lexicographical Substring Search

SUBLEX - Lexicographical Substring Search no tags 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 q

Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)

Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串,求出这个字符串上字典序第 \(k\) 小的子串. 思路 先对给出的字符串构建后缀自动机,因为后缀自动机上从根节点走到任意节点都是原串的一个子串,所以我们可以 \(dfs\) 求出节点 \(i\) 往后存在多少个子串. 对于查询第 \(k\) 小的子串时,在用一个 \(dfs\) 来求,对于当前节点

Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)

Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串,求出这个字符串上字典序第 \(k\) 小的子串. 思路 对于给出的字符串,求出后缀数组,根据后缀数组的 \(height\) 数组,我们可以很容易得到一个字符的总子串个数是 \(\sum_{i=1}^{n} (n-sa[i]+1+height[i])\),利用这个式子,就可以求出第 \(k\) 小

【spoj7528】 Lexicographical Substring Search

http://www.spoj.com/problems/SUBLEX/ (题目链接) 题意 给出一个字符串,询问其中字典序第K小的子串. Solution 后缀自动机例题. 构出后缀自动机以后,对每个节点预处理出从这个节点可以到达多少个不同的子串.然后就是类似于在平衡树上查找一样沿着SAM一路查找下去一路更新答案了. 代码借鉴的DaD3Zz大神,感觉好优美. 细节 后缀自动机的节点数是2N的. 代码 // spoj7528 #include<algorithm> #include<io

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

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

[SPOJ7258]Lexicographical Substring Search

试题描述 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 substri

【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单独算一个子串. 然后

SPOJ SUBLEX Lexicographical Substring Search - 后缀数组

题目传送门 传送门I 传送门II 题目大意 给定一个字符串,多次询问它的第$k$大本质不同的子串,输出它. 考虑后缀Trie.依次考虑每个后缀新增的本质不同的子串个数,显然,它是$n - sa[i] - height[i]$. 求出$height$数组后,求一求本质不同的子串个数的前缀和,可以对每个询问二分. 这里可以直接离线,$O(n + m)$扫一扫就好了. Code 1 /** 2 * SPOJ 3 * Problem#SUBLEX 4 * Accepted 5 * Time: 30ms