zoukankan      html  css  js  c++  java
  • 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
    ", 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;
    }
  • 相关阅读:
    Servlet总结06——servlet过滤器
    jdbc 事务及事务隔离
    集群中几种session同步解决方案的比较[转]
    Servlet总结05——servlet监听器
    Servlet总结(系列文章)
    Eclipse导入Tomcat源码
    Servlet总结02——请求转发
    Servlet总结01——servlet的主要接口、类
    [ lucene其他 ] 几种常见的基于Lucene的开源搜索解决方案对比[转]
    Servlet总结04——注意Servlet单实例的线程安全性
  • 原文地址:https://www.cnblogs.com/gggyt/p/7604872.html
Copyright © 2011-2022 走看看