• [Codeforces 204E] Little Elephant and Strings


    [题目链接]

             https://codeforces.com/contest/204/problem/E

    [算法]

            首先构建广义后缀自动机

            对于自动机上的每个节点 , 维护一棵平衡树存储所有它所匹配的字符串编号

            可以通过启发式合并得到

            计算答案时 , 我们枚举每个右端点 , 当当前集合大小 < K时 , 不断走向link节点

            时间复杂度 : O(NlogN)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int N = 2e5 + 10;
    const int ALPHA = 26;
    #define rint register int
    
    int n , k;
    string st[N];
    
    struct Suffix_Automaton
    {
            int sz , last;
            int father[N] , depth[N] , child[N][ALPHA] , cnt[N];
            set< int > s[N];
            vector< int > a[N];
            Suffix_Automaton()
            {
                    sz = 1;
                    last = 1;        
            }        
            inline int new_node(int dep)
            {
                    depth[++sz] = dep;
                    father[sz] = 0;
                    memset(child[sz] , 0 , sizeof(child[sz]));
                    return sz;
            }
            inline void extend(int ch , int col)
            {
                    int np = child[last][ch];
                    if (np)
                    {    
                            if (depth[np] == depth[last] + 1)
                            {
                                    s[np].insert(col);
                                    last = np;
                                    return;
                            } else
                            {
                                    int nq = new_node(depth[last] + 1);
                                    father[nq] = father[np];
                                    father[np] = nq;
                                    memcpy(child[nq] , child[np] , sizeof(child[nq]));
                                    for (int p = last; child[p][ch] == np; p = father[p])
                                            child[p][ch] = nq;
                                    s[nq].insert(col);
                                    last = nq;
                                    return;
                            }
                    } else
                    {
                            np = new_node(depth[last] + 1);
                            int p = last;
                            for (; child[p][ch] == 0; p = father[p])
                                    child[p][ch] = np;
                            if (child[p][ch] == np)
                            {
                                    father[np] = 1;
                                    s[np].insert(col);
                                    last = np;
                                    return;
                            } else
                            {
                                    int q = child[p][ch];
                                    if (depth[q] == depth[p] + 1)
                                    {
                                            father[np] = q;
                                            s[np].insert(col);
                                            last = np;
                                            return;
                                    } else
                                    {
                                            int nq = new_node(depth[p] + 1);
                                            father[nq] = father[q];
                                            father[np] = father[q] = nq;
                                            memcpy(child[nq] , child[q] , sizeof(child[nq]));
                                            for (; child[p][ch] == q; p = father[p])
                                                    child[p][ch] = nq;
                                            s[np].insert(col);
                                            last = np;
                                    }
                            }
                    }
            }
            inline void insert(string s , int col)
            {
                    last = 1;
                    for (rint i = 0; i < (int)s.size(); ++i)
                            extend(s[i] - 'a' , col);
            }
            inline void dfs(int u)
            {
                    for (unsigned i = 0; i < a[u].size(); ++i)
                    {
                            int v = a[u][i];
                            dfs(v);
                            if ((int)s[u].size() < (int)s[v].size())
                                    swap(s[u] , s[v]);
                            for (set< int > :: iterator it = s[v].begin(); it != s[v].end(); ++it)
                                    s[u].insert(*it);                        
                    }
                    cnt[u] = (int)s[u].size();
            }
            inline void work()
            {
                    for (rint i = 2; i <= sz; ++i)
                            a[father[i]].push_back(i);
                    dfs(1);
            }
    } SAM;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    
    int main()
    {
            
            read(n); read(k);
            for (rint i = 1; i <= n; ++i)
            {
                    cin >> st[i];
                    SAM.insert(st[i] , i);        
            }
            SAM.work();
            for (rint i = 1; i <= n; ++i)
            {
                    int now = 1;
                    ll ans = 0;
                    for (rint j = 0; j < st[i].size(); ++j)
                    {
                            now = SAM.child[now][st[i][j] - 'a'];
                            while (now != 1 && SAM.cnt[now] < k) now = SAM.father[now];
                            ans += (ll)SAM.depth[now]; 
                    }        
                    printf("%lld " , ans);
            }
            printf("
    ");
            
            return 0;
        
    }
  • 相关阅读:
    深入浅出SQL Server 2008 分区函数和分区表
    数据库的恢复模式
    Windows Server 2003网络负载均衡的实现(转)
    SharePoint2010网站备份还原简单介绍
    HTTP协议详解(转)
    SharePoint 2010之LINQ与SPMetal
    moss 自定义文档库文档图标
    SharePoint 2010环境搭建
    C#中的yield关键字
    .NET开发中你可能会用到的常用方法总结(添加ing...)
  • 原文地址:https://www.cnblogs.com/evenbao/p/10660063.html
Copyright © 2020-2023  润新知