zoukankan      html  css  js  c++  java
  • [CF128B] String

    [CF128B] String - SAM,dp

    Description

    求给定字符串的字典序第 (k) 小子串(允许重复)。

    Solution

    SAM 上 dp,预处理出 (endpos) 集合大小 (cnt[p]),则 (f[p]=sum_{p o q} f[q] + cnt[p])

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 1000005;
    struct SAM
    {
        int len[N], ch[N][26], fa[N], ind, last;
        int t[N], a[N], cnt[N], f[N];
        SAM() { ind = last = 1; }
        inline void extend(int id)
        {
            int cur = (++ind), p;
            len[cur] = len[last] + 1;
            cnt[cur] = 1;
            for (p = last; p && !ch[p][id]; p = fa[p])
                ch[p][id] = cur;
            if (!p)
                fa[cur] = 1;
            else
            {
                int q = ch[p][id];
                if (len[q] == len[p] + 1)
                    fa[cur] = q;
                else
                {
                    int tmp = (++ind);
                    len[tmp] = len[p] + 1;
                    for (int i = 0; i < 26; i++)
                        ch[tmp][i] = ch[q][i];
                    fa[tmp] = fa[q];
                    for (; p && ch[p][id] == q; p = fa[p])
                        ch[p][id] = tmp;
                    fa[cur] = fa[q] = tmp;
                }
            }
            last = cur;
        }
        void calcEndpos()
        {
            memset(t, 0, sizeof t);
            for (int i = 1; i <= ind; i++)
                t[len[i]]++;
            for (int i = 1; i <= ind; i++)
                t[i] += t[i - 1];
            for (int i = 1; i <= ind; i++)
                a[t[len[i]]--] = i;
            for (int i = ind; i >= 1; --i)
                cnt[fa[a[i]]] += cnt[a[i]];
            cnt[1] = 0;
        }
        void DFS(int p)
        {
            for (int i = 0; i < 26; i++)
            {
                if (ch[p][i])
                {
                    if (f[ch[p][i]] == 0)
                        DFS(ch[p][i]);
                    f[p] += f[ch[p][i]];
                }
            }
            f[p] += cnt[p];
        }
        void Go(int p, int k)
        {
            k -= cnt[p];
            for (int i = 0; i < 26 && k > 0; i++)
            {
                if (ch[p][i])
                {
                    if (f[ch[p][i]] >= k)
                    {
                        cout << (char)(i + 'a');
                        Go(ch[p][i], k);
                        return;
                    }
                    else
                    {
                        k -= f[ch[p][i]];
                    }
                }
            }
            if (k > 0)
            {
                cout << "No such line.";
                exit(0);
            }
        }
    } sam;
    
    signed main()
    {
        ios::sync_with_stdio(false);
        string str;
        cin >> str;
        int t, k;
        for (int i = 0; i < str.length(); i++)
            sam.extend(str[i] - 'a');
        sam.calcEndpos();
        sam.DFS(1);
        cin >> k;
        sam.Go(1, k);
    }
    
    
  • 相关阅读:
    day35-python-网络编程
    oc-继承(inherit) 方法重写 继承与组合
    oc-self关键字
    oc-类方法
    oc-封装 get set方法
    oc-匿名对象
    oc-函数命名
    oc-函数,方法,类
    解决"authentication token manipulation error"
    让tomcat自动定位到项目
  • 原文地址:https://www.cnblogs.com/mollnn/p/14661218.html
Copyright © 2011-2022 走看看