[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("\n");
        
        return 0;
    
}

 

上一篇:Python数据分析学习笔记-numpy库学习2


下一篇:04 张量的线性代数运算