【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单独算一个子串。
然后查找的时候从root出发(你可以这样想,因为root的right值包含了所有right,即root有所有后缀的r下标,所以只需要找最小的开头即可,然后转移后同理。
然后如果当前的转移的状态y,有s[y]>=k,那么说明子串在y的后缀里边,那么--k并且打印字符y后转移到y状态。(--k是因为我们转移的定义)
反之,如果s[y]<k, k-=s[y]
然后就行了。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } struct sam {
static const int N=250005;
int c[N][26], l[N], f[N], root, last, cnt, sz[N], o[N];
sam() { cnt=0; root=last=++cnt; }
void add(int x) {
int now=last, a=++cnt; last=a;
l[a]=l[now]+1;
for(; now && !c[now][x]; now=f[now]) c[now][x]=a;
if(!now) f[a]=root;
else {
int q=c[now][x];
if(l[q]==l[now]+1) f[a]=q;
else {
int b=++cnt;
memcpy(c[b], c[q], sizeof c[q]);
l[b]=l[now]+1;
f[b]=f[q];
f[q]=f[a]=b;
for(; now && c[now][x]==q; now=f[now]) c[now][x]=b;
}
}
}
void build(char *s) {
int len=strlen(s);
rep(i, len) add(s[i]-'a');
for1(i, 1, cnt) sz[l[i]]++;
for1(i, 1, len) sz[i]+=sz[i-1];
for1(i, 1, cnt) o[sz[l[i]]--]=i;
for1(i, 0, len) sz[i]=0;
for1(i, 1, cnt) sz[i]=1;
for3(i, cnt, 1) {
int p=o[i];
rep(x, 26) sz[p]+=sz[c[p][x]];
}
}
void getans(int k) {
int now=root;
while(k) {
rep(x, 26) if(c[now][x]) {
int y=c[now][x];
if(sz[y]>=k) { putchar('a'+x); --k; now=y; break; }
else k-=sz[y];
}
}
puts("");
}
}a; const int N=150005;
char s[N];
int main() {
scanf("%s", s);
a.build(s);
int q=getint();
while(q--) a.getans(getint());
return 0;
}
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 Qquestions of the form:
If all distinct substrings of string S were sorted lexicographically, which one will be the K-thsmallest?
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
【SPOJ】7258. Lexicographical Substring Search(后缀自动机)的更多相关文章
- spoj 7258 Lexicographical Substring Search (后缀自动机)
spoj 7258 Lexicographical Substring Search (后缀自动机) 题意:给出一个字符串,长度为90000.询问q次,每次回答一个k,求字典序第k小的子串. 解题思路 ...
- SPOJ 7258 Lexicographical Substring Search [后缀自动机 DP]
题意:给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 第一道自己做的1A的SAM啦啦啦 很简单,建SAM后跑kth就行了 也需要按val基数排序倒着 ...
- SPOJ SUBLEX - Lexicographical Substring Search 后缀自动机 / 后缀数组
SUBLEX - Lexicographical Substring Search Little Daniel loves to play with strings! He always finds ...
- ●SPOJ 7258 Lexicographical Substring Search
题链: http://www.spoj.com/problems/SUBLEX/题解: 后缀自动机. 首先,因为相同的子串都被存在了自动机的同一个状态里面,所以这就很自然的避免了重复子串的问题. 然后 ...
- SPOJ 7258 Lexicographical Substring Search(后缀自动机)
[题目链接] http://www.spoj.com/problems/SUBLEX/ [题目大意] 给出一个字符串,求其字典序排名第k的子串 [题解] 求出sam上每个节点被经过的次数,然后采用权值 ...
- SPOJ Lexicographical Substring Search 后缀自动机
给你一个字符串,然后询问它第k小的factor,坑的地方在于spoj实在是太慢了,要加各种常数优化,字符集如果不压缩一下必t.. #pragma warning(disable:4996) #incl ...
- SPOJ SUBLEX Lexicographical Substring Search - 后缀数组
题目传送门 传送门I 传送门II 题目大意 给定一个字符串,多次询问它的第$k$大本质不同的子串,输出它. 考虑后缀Trie.依次考虑每个后缀新增的本质不同的子串个数,显然,它是$n - sa[i] ...
- SPOJ 7258 Lexicographical Substring Search
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
- SP7258 SUBLEX - Lexicographical Substring Search - 后缀自动机,dp
给定一个字符串,求本质不同排名第k小的子串 Solution 后缀自动机上每条路径对应一个本质不同的子串 按照 TRANS 图的拓扑序,DP 计算出每个点发出多少条路径 (注意区别 TRANS 图的拓 ...
- SPOJ7258 SUBLEX - Lexicographical Substring Search(后缀自动机)
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
随机推荐
- HDOJ 1870
#include<stdio.h> #include<stack> #include<string.h> #include<iostream> usin ...
- shell脚本检测局域网内存活主机
<1> d211 admin # for i in {3..254} ; do ping -c 1 192.168.1.$i &>/dev/null && e ...
- win7系统扩展双屏幕时,如何在两个屏幕下都显示任务栏
扩展屏幕下都显示任务栏!!! win7系统本身无法设置该功能(目前我是不知道) 但可以下载第三方软件来解决该问题. 第一步:Dual Monitor Taskbar 下载软件 下载链接:http:// ...
- 开发Web Service的几种方式
本文作者在学习使用Java开发Web Service(不包括Restful)时,由于不知道Java有这么多框架支持开发Web Service一度陷入迷惘,不知道这些框架各有 什么不同,各有什么优缺点. ...
- svn 设置
\Release *\Debug *\bin *\Bin *\obj *\_ReSharper* *\.hg *.ReSharper *.resharper *\Generated_Code *\VB ...
- 如何使用box2d做碰撞检测
cocos2dx3.0+vs2012编译通过. 主要是通过body->SetTransform来设置body的位置和角度,然后自己写个ContactListener来监听碰撞事件 源代码下载 # ...
- (转)SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)
五.锁与事务隔离级别 事务隔离级别简单的说,就是当激活事务时,控制事务内因SQL语句产生的锁定需要保留多入,影响范围多大,以防止多人访问时,在事务内发生数据查询的错误.设置事务隔离级别将影响整条连接. ...
- poj 3750 小孩报数问题 解题报告
题目链接:http://poj.org/problem?id=3750 约瑟夫问题,直接模拟即可. #include <iostream> #include <string> ...
- Codeforces 417 C
Football Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Submit Sta ...
- [Android Pro] 监听Blutooth打开广播
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission a ...