zoukankan      html  css  js  c++  java
  • SPOJ 7258 Lexicographical Substring Search

    SPOJ_7258 SUBLEX

        这个题目可以先用O(N)的时间构造出后缀自动机,由于后缀自动机中每条路径都对应着一个不重复的子串,因此可以用dp处理出到达一个节点以及其后面的节点的路径数,然后每次查询时遍历一遍后缀自动机就可以了。

        但这样总的查询复杂度是O(N*Q)的,如果不用各种常数优化的话很容易TLE。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 90010
    struct SufAuto
    {
        int pre, next[26], len;
    }sa[2 * MAXD];
    namespace SA
    {
        int node, tail;
        void init()
        {
            node = tail = 0;
            sa[0].pre = -1;
        }
        void insert(int k, int len)
        {
            int p = tail, np = ++ node;
            sa[np].len = len;
            for(; p != -1 && !sa[p].next[k]; p = sa[p].pre) sa[p].next[k] = np;
            tail = np;
            if(p == -1) sa[np].pre = 0;
            else
            {
                if(sa[sa[p].next[k]].len == sa[p].len + 1) sa[np].pre = sa[p].next[k];
                else
                {
                    int q = sa[p].next[k], r = ++ node;
                    sa[r] = sa[q], sa[r].len = sa[p].len + 1;
                    sa[q].pre = sa[np].pre = r;
                    for(; p != -1 && sa[p].next[k] == q; p = sa[p].pre) sa[p].next[k] = r;
                }
            }
        }
    }
    char b[MAXD];
    int N, q[2 * MAXD], h[MAXD], f[2 * MAXD], num[2 * MAXD][26], next[2 * MAXD][26];
    char ch[2 * MAXD][26];
    void init()
    {
        int i;
        SA::init();
        for(i = 0; b[i]; i ++) SA::insert(b[i] - 'a', i + 1);
        N = i;
    }
    void solve()
    {
        int i, j, k, x, cur, t, rear, n;
        for(i = 0; i <= N; i ++) h[i] = 0;
        for(i = 1; i <= SA::node; i ++) ++ h[sa[i].len];
        for(i = 1; i <= N; i ++) h[i] += h[i - 1];
        for(i = SA::node; i >= 1; i --) q[-- h[sa[i].len]] = i;
        for(i = SA::node - 1; i >= 0; i --)
        {
            x = q[i];
            for(j = 0; j < 26; j ++) f[x] += f[sa[x].next[j]];
            ++ f[x];
        }
        for(i = 0; i <= SA::node; i ++)
            for(j = k = 0; j < 26; j ++)
                if(f[sa[i].next[j]])
                    next[i][k] = sa[i].next[j], num[i][k] = f[sa[i].next[j]], ch[i][k] = j + 'a', ++ k;    
        scanf("%d", &t);
        while(t --)
        {
            scanf("%d", &n);
            for(i = k = 0; i < 26; i ++) k += num[0][i];
            n = (n - 1) % k + 1;
            rear = cur = 0;
            for(;;)
            {
                if(n == 0) break;
                for(i = 0; i < 26 && n > num[cur][i]; n -= num[cur][i ++]);
                -- n;
                b[rear ++] = ch[cur][i];
                cur = next[cur][i];
            }
            b[rear] = '\0';
            puts(b);
        }
    }
    int main()
    {
        scanf("%s", b);
        init();
        solve();
        return 0;    
    }
  • 相关阅读:
    mongo的csv文件参考
    apache安装配置
    部署Java的运行环境
    ubuntu下没有ping命令
    webbench压力测试
    判断当前是否是微信浏览器,还是APP客户端
    PHP uniqid 高并发生成不重复唯一ID
    http_build_query()函数使用方法
    防XSS攻击
    PHP中json_encode()使用须知,JSON数组和JSON对象
  • 原文地址:https://www.cnblogs.com/staginner/p/2680365.html
Copyright © 2011-2022 走看看