Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)
Posted jiaaaaaaaqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)相关的知识,希望对你有一定的参考价值。
Lexicographical Substrings Search
\[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \]
题意
给出一个字符串,求出这个字符串上字典序第 \(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 (后缀自动机)的主要内容,如果未能解决你的问题,请参考以下文章
SPOJ SUBLEX - Lexicographical Substring Search 后缀自动机 / 后缀数组
spoj7528 Lexicographical Substring Search
Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)
●SPOJ 7258 Lexicographical Substring Search