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大字串的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ7258

SPOJ 7258 Lexicographical Substring Search(后缀自动机)

●SPOJ 7258 Lexicographical Substring Search

Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)

SPOJ SUBLEX Lexicographical Substring Search - 后缀数组

Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)