spoj 7258 SUBLEX(求第k大字串
Posted gggyt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spoj 7258 SUBLEX(求第k大字串相关的知识,希望对你有一定的参考价值。
其实对sam的拓扑排序我似懂非懂但是会用一点了。
/** @xigua */ #include <stdio.h> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <cstring> #include <queue> #include <set> #include <string> #include <map> #include <climits> #define PI acos(-1) #define rep(a,b,c) for(int (a)=(b); (a)<(c); ++(a)) #define drep(a,b,c) for(int (a)=(b); (a)>(c); --(a)) #define CLR(x) memset(x, 0, sizeof(x)) #define sf scanf #define pf printf using namespace std; typedef long long ll; typedef double db; const int maxn = 250005*2 + 1000; const int ma = 1e5 + 1000; const int mod = 1e9 + 7; const int INF = 1e8 + 5; const ll inf = 1e17 + 5; const db eps = 1e-6; const int MAXN = 2e5+1e3; struct SAM{ int ch[maxn<<1][26]; int fa[maxn<<1], len[maxn<<1]; int cnt, last, root; void init() { root=1; memset(ch, 0, sizeof(ch)); memset(fa, 0, sizeof(fa)); last=cnt=root; } void add(int c) { int p=last, np=last=++cnt; len[np]=len[p]+1; while(!ch[p][c] && p) { ch[p][c]=np; p=fa[p]; } if (p==0) fa[np]=1; else { int q = ch[p][c]; if(len[p] + 1 == len[q]) { fa[np] = q; } else { int nq = ++cnt; len[nq] = len[p] + 1; memcpy(ch[nq], ch[q], sizeof ch[q]); fa[nq] = fa[q]; fa[q] = fa[np] = nq; while(ch[p][c] == q && p) { ch[p][c] = nq; p = fa[p]; } } } } int find(char *s) { int p=root, l=0, c=0; int lenn=strlen(s); for(int i = 0; i < lenn; i++) { if(ch[p][s[i] - ‘a‘]) { p = ch[p][s[i] - ‘a‘]; c++; } else { while(p&&!ch[p][s[i]-‘a‘]) p=fa[p]; if (!p) c=0, p=1; else c=len[p]+1, p=ch[p][s[i]-‘a‘]; } l = max(l, c); } printf("%d\n", l); } }sam; char s[maxn]; int c[maxn<<1], pt[maxn<<1], f[maxn]; void innt() { memset(pt, 0, sizeof(pt)); memset(c, 0, sizeof(c)); memset(f, 0, sizeof(f)); } void top() { for (int i=1; i<=sam.cnt; i++) c[sam.len[i]]++; for (int i=1; i<=sam.cnt; i++) c[i]+=c[i-1]; for (int i=sam.cnt; i>=1; i--) pt[c[sam.len[i]]--]=i; // /*拓扑排序*/ // for (int i=sam.cnt; i; i--) { f[pt[i]]=1; for (int j=0; j<26; j++) { f[pt[i]]+=f[sam.ch[pt[i]][j]]; //相同前缀的字符串个数 } } } void solve() { innt(); scanf("%s", s); int lenn=strlen(s); sam.init(); for (int i=0; i<lenn; i++) { sam.add(s[i]-‘a‘); } top(); int q; scanf("%d", &q); while(q--) { int x; scanf("%d", &x); int p=sam.root; /*我们找第k大的字串就在f上转移就好了*/ while(x) { for (int i=0; i<26; i++) { if (sam.ch[p][i]) { if (f[sam.ch[p][i]]>=x) { putchar(‘a‘+i); p=sam.ch[p][i]; --x; break; } else x-=f[sam.ch[p][i]]; } } } puts(""); } } int main() { int t = 1, cas = 1; // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); //scanf("%d", &t); while(t--) { // printf("Case %d: ", cas++); solve(); } return 0; }
以上是关于spoj 7258 SUBLEX(求第k大字串的主要内容,如果未能解决你的问题,请参考以下文章
SPOJ 7258 Lexicographical Substring Search(后缀自动机)
●SPOJ 7258 Lexicographical Substring Search
Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)