[spoj7258]Lexicographical Substring Search && 后缀自动机

来源:互联网 发布:淘宝标题优化在哪里 编辑:程序博客网 时间:2024/05/25 20:00

建立完后缀自动机过后用f[i]表示节点i以及i的儿子缩代表的串的个数

排序过后由深的点往浅的点更新

询问的时候进去跑一跑就好

SPOJ时间限制真是紧

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>#define SF scanf#define PF printf#define idx(c) (c-'a')using namespace std;typedef long long LL;const int MAXN = 180000;int n;char s[MAXN+10];struct SAM {int fa[MAXN+10], ch[MAXN+10][26], step[MAXN+10];int f[MAXN+10], last, ncnt, v[MAXN+10], sa[MAXN+10];void extend(int c) {int p = last, np = last = ++ncnt;n = step[np] = step[p]+1;while(!ch[p][c] && p) ch[p][c] = np, p = fa[p];if(!p) fa[np] = 1;else {int q = ch[p][c], nq;if(step[q] == step[p]+1) fa[np] = q;else {nq = ++ncnt;step[nq] = step[p]+1;memcpy(ch[nq], ch[q], sizeof(ch[nq]));fa[nq] = fa[q]; fa[np] = fa[q] = nq;while(ch[p][c] == q && p) ch[p][c] = nq, p = fa[p];}}}inline void build() {SF("%s", s);for(char *c = s; *c; c++) extend(*c-'a');} inline void solve() {for(int i = 1; i <= ncnt; i++) v[step[i]]++;for(int i = 1; i <= n; i++) v[i] += v[i-1];for(int i = 1; i <= ncnt; i++) sa[v[step[i]]--] = i;for(int i = ncnt; i >= 1; i--) {f[sa[i]] = 1;for(int j = 0; j < 26; j++)f[sa[i]] += f[ch[sa[i]][j]];}}inline void query() {int k, u = 1;SF("%d", &k);while(k) {for(int c = 0; c < 26; c++) if(ch[u][c]) {if(f[ch[u][c]] < k) k -= f[ch[u][c]];else {k--;putchar('a'+c);u = ch[u][c];                                                break;}}}puts("");}} ac;int main() {ac.last = ac.ncnt = 1;ac.build();ac.solve();int Q; SF("%d", &Q);for(int i = 1; i <= Q; i++)ac.query();}


0 0
原创粉丝点击