Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)
Lexicographical Substrings Search
\]
题意
给出一个字符串,求出这个字符串上字典序第 \(k\) 小的子串。
思路
先对给出的字符串构建后缀自动机,因为后缀自动机上从根节点走到任意节点都是原串的一个子串,所以我们可以 \(dfs\) 求出节点 \(i\) 往后存在多少个子串。
对于查询第 \(k\) 小的子串时,在用一个 \(dfs\) 来求,对于当前节点\(u\), 从\(1-26\) 枚举下一步的方案 \(v\),如果从 \(v\) 往后的子串比 \(k\) 少,那么不用往下走,直接 \(k-=cnt[v]\)。否则往下走一步,让 \(k--\)。如此一直走到 \(k=0\) 为止。
/***************************************************************
> File Name : a.cpp
> Author : Jiaaaaaaaqi
> Created Time : 2019年05月22日 星期三 17时06分12秒
***************************************************************/
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
struct SAM {
struct Node{
int next[27];
int fa, len;
void init() {
mes(next, 0);
len = fa = 0;
}
} node[maxn<<1];
int sz, last;
int cnt[maxn<<1];
void init() {
sz = last = 1;
node[sz].init();
mes(cnt, 0);
}
void insert(int k) {
int p = last, np = last = ++sz;
node[np].init();
node[np].len = node[p].len+1;
for(; p&&!node[p].next[k]; p=node[p].fa)
node[p].next[k] = np;
if(p==0) {
node[np].fa = 1;
} else {
int q = node[p].next[k];
if(node[q].len == node[p].len + 1) {
node[np].fa = q;
} else {
int nq = ++sz;
node[nq] = node[q];
node[nq].len = node[p].len + 1;
node[np].fa = node[q].fa = nq;
for(; p&&node[p].next[k]==q; p=node[p].fa)
node[p].next[k] = nq;
}
}
}
void dfs(int u) {
if(cnt[u]) return ;
cnt[u] = 1;
for(int i=1; i<=26; i++) {
int v = node[u].next[i];
if(v) {
dfs(v);
cnt[u] += cnt[v];
}
}
}
char ss[maxn];
void find(int u, int k, int len) {
if(k==0) {
ss[len] = '\0';
printf("%s\n", ss+1);
return ;
}
for(int i=1; i<=26; i++) {
int v = node[u].next[i];
if(v==0) continue;
if(cnt[v] < k) k -= cnt[v];
else {
k--;
ss[len] = 'a'+i-1;
find(v, k, len+1);
return ;
}
}
}
void solve(int k) {
find(1, k, 1);
}
} sam;
char s[maxn];
int main() {
sam.init();
scanf("%s", s+1);
int len = strlen(s+1);
for(int i=1; i<=len; i++) {
sam.insert(s[i]-'a'+1);
}
sam.dfs(1);
// for(int i=2; i<=sam.sz; i++) {
// printf("cnt[%d] = %d\n", i, sam.cnt[i]);
// }
scanf("%d", &T);
while(T--) {
scanf("%d", &m);
sam.solve(m);
}
return 0;
}
Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)的更多相关文章
- Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)
Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串 ...
- Lexicographical Substring Search (spoj7259) (sam(后缀自动机)+第k小子串)
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
- SPOJ - SUBLEX 后缀自动机
SPOJ - SUBLEX 思路:求第k大字串,求出sam上每个节点开始能识别多少字串,然后从起点开始跑就好啦. #include<bits/stdc++.h> #define LL lo ...
- SPOJ SUBLEX - Lexicographical Substring Search 后缀自动机 / 后缀数组
SUBLEX - Lexicographical Substring Search Little Daniel loves to play with strings! He always finds ...
- spoj 7258 Lexicographical Substring Search (后缀自动机)
spoj 7258 Lexicographical Substring Search (后缀自动机) 题意:给出一个字符串,长度为90000.询问q次,每次回答一个k,求字典序第k小的子串. 解题思路 ...
- 【SPOJ】7258. Lexicographical Substring Search(后缀自动机)
http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一 ...
- SPOJ SUBLEX 7258. Lexicographical Substring Search
看起来像是普通的SAM+dfs...但SPOJ太慢了......倒腾了一个晚上不是WA 就是RE ..... 最后换SA写了...... Lexicographical Substring Searc ...
- [SPOJ7258]Lexicographical Substring Search
[SPOJ7258]Lexicographical Substring Search 试题描述 Little Daniel loves to play with strings! He always ...
- 【SPOJ - SUBLEX】Lexicographical Substring Search 【后缀自动机+dp】
题意 给出一个字符串和q个询问,每个询问给出一个整数k,输出第k大得子串. 分析 建后缀自动机,利用匹配边来解决.设d[v]为从状态v开始有多少不同的路径.这个显然是可以递推出来的.然后对于每个询问, ...
随机推荐
- Python将背景图片的颜色去掉
一.问题 在使用图片的时候有时候我们希望把背景变成透明的,这样就只关注于图片本身.比如在连连看中就只有图片,而没有背景,其实我个人感觉有背景好看一点. 二.解决 我们需要使用RGBA(Red,Gr ...
- Github Markdown 图片如何并排显示
Github Markdown 图片如何并排显示 要一张图片接着一张图片的写,中间不能有换行.如果换行的话则图片也换行 正确的写法: ?[-]{,}$|^?[|||7||][-]\d{}$/; //验证的手机号码格式 //this.ruleForm.adminC ...
- Vue笔记目录
Vue笔记目录 一.Vue.js介绍 二.vue基础-vue-cli(vue脚手架) ...持续更新中,敬请期待
- Django 中使用 MarkDown 插件
目录 Django 使用 markdown 插件 1 将 markdown 转化为 html 2 使用 markdown 编辑框 Django 使用 markdown 插件 Python-Markdo ...
- iOS RACSubject代替通知
RAC是一个很常用并且很好用的插件,简洁的调用方式可以代替很多原生方法,下面是RACSubject代替通知的使用方式: #import <UIKit/UIKit.h> #import &l ...
- git使用.gitignore文件忽略相关文件上传
在使用git时,有些文件是不需要上传到仓库中的,比如idea/eclipse相关的文件,编译后的文件(target目录)等. 可以使用.gitignore文件进行配置.在git本地仓库创建.gitig ...
- Django之ORM数据查询方式练习
单表查询 单表查询简单示例 # 字段 models.DateField(auto_now_add) models.DateField(auto_now) # auto_now 和auto_now_ad ...