zoukankan      html  css  js  c++  java
  • 【题解】【LOJ2102】「TJOI2015」弦论

    题目链接

    点击打开链接

    题目解法

    后缀自动机入门题。

    建立后缀自动机。求第 (k) 大可以考虑按位确定。把后缀自动机当成一个 trie 树看,每次类似于平衡树上查找第 k 大的方式查找即可。

    总结

    没啥。

    代码

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int CN = 5e5 + 5, CNODE = 1e6 + 5;
    struct SAM {
        int edge[26], parent, len, size;
        bool leaf;
    } node[CNODE];
    int last, ntot, N, T, K, topo[CNODE], buc[CN], num[2][CNODE];
    int cnt = 0;
    void Extend(int c) {
        ++cnt;
        int p = last, newnode = ++ntot;
        node[newnode].len = node[last].len + 1;
        //先计算 newnode的 len,再将 last变成 newnode
        last = newnode;
        node[newnode].leaf = 1;
        for (; p && node[p].edge[c] == 0; p = node[p].parent) node[p].edge[c] = newnode;
        if (!p)
            node[newnode].parent = 1;
        else {
            int q = node[p].edge[c];
            if (node[q].len == node[p].len + 1)
                node[newnode].parent = q;
            else {
                int clone = ++ntot;
                for (int i = 0; i < 26; ++i) node[clone].edge[i] = node[q].edge[i];
                node[clone].leaf = 0;
                // clone的 endpos
                node[clone].parent = node[q].parent;
                node[clone].len = node[p].len + 1;
                node[q].parent = node[newnode].parent = clone;
                for (; p && node[p].edge[c] == q; p = node[p].parent) node[p].edge[c] = clone;
            }
        }
    }
    void GetSize() {
        for (int i = 1; i <= ntot; ++i) ++buc[node[i].len];
        for (int i = 1; i <= N; ++i) buc[i] += buc[i - 1];
        for (int i = 1; i <= ntot; ++i) {
            topo[buc[node[i].len]--] = i;
            node[i].size = node[i].leaf;
        }
        for (int i = ntot; i >= 1; --i) {
            node[node[topo[i]].parent].size += node[topo[i]].size;
            if (topo[i] != 1) {
                num[0][topo[i]] = 1;
                num[1][topo[i]] = node[topo[i]].size;
            }
            for (int j = 0; j < 26; ++j) {
                if (node[topo[i]].edge[j]) {
                    num[0][topo[i]] += num[0][node[topo[i]].edge[j]];
                    num[1][topo[i]] += num[1][node[topo[i]].edge[j]];
                }
            }
        }
    }
    void Find() {
        int now = 1;
        node[1].size = 0;
        if (T == 0)
            for (int i = 2; i <= ntot; ++i) node[i].size = 1;
        num[T][1] = 0;
        while (K > node[now].size) {
            for (int i = 0; i < 26; ++i) {
                if (!node[now].edge[i])
                    continue;
                if (K <= num[T][node[now].edge[i]]) {
                    K -= node[now].size;
                    now = node[now].edge[i];
                    printf("%c", (char)i + 'a');
                    break;
                } else
                    K -= num[T][node[now].edge[i]];
            }
        }
        printf("
    ");
    }
    char str[CN];
    int main() {
        scanf("%s%d%d", str + 1, &T, &K);
        N = strlen(str + 1);
        last = ntot = 1;
        for (int i = 1; i <= N; ++i) Extend(str[i] - 'a');
        GetSize();
        if (num[T][1] < K)
            printf("-1
    ");
        else
            Find();
        return 0;
    }
    
  • 相关阅读:
    leetcode-594-Longest Harmonious Subsequence
    leetcode-581-Shortest Unsorted Continuous Subarray
    leetcode-575-Distribute Candies(计算一个数组中元素的种类的快速方法)
    leetcode-566-Reshape the Matrix
    leetcode-561-Array Partition I
    leetcode-551-Student Attendance Record I(判断是否出现连续几个相同字符)
    Java之CheckedException
    Java异常机制
    Zookeeper分布式协调即分布式锁机制
    Spring中@Value用法
  • 原文地址:https://www.cnblogs.com/YouthRhythms/p/13344828.html
Copyright © 2011-2022 走看看