zoukankan      html  css  js  c++  java
  • [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;
        
    }
  • 相关阅读:
    来自Jakob Jenkov的Jackson教程
    Linux查看某个端口的连接数
    Linux查看某个进程的线程
    Jackson反序列JSON为实体对象出现:no String-argument constructor/factory method to deserialize from String value的问题
    软路由OpenWrt教程收集(插件开发教程,opkg安装软件教程)
    软路由系统收集
    Linux防止“rm -rf /”误删除
    Mac 10.12原生方法对NTFS分区进行读写的配置
    Linux下进行Web服务器压力(并发)测试工具http_load、webbench、ab、Siege、autobench简单使用教程(转)
    微服务实施Spring Boot/Spring Cloud中踩过的坑(转)
  • 原文地址:https://www.cnblogs.com/evenbao/p/10660063.html
Copyright © 2011-2022 走看看