1. 程式人生 > >spoj 7258 SUBLEX(求第k大字串

spoj 7258 SUBLEX(求第k大字串

top stdin add algo can find size esp con

  其實對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大字串