zoukankan      html  css  js  c++  java
  • 2020牛客多校 第四场 C Count New String(广义后缀自动机)

    题意等价于对(S)(|S|)个后缀进行(f)操作,求这|S|个操作后的后缀的本质不同的子串个数


    把每个操作后的后缀翻转后插入字典树
    当所有后缀都插入字典树之后建广义后缀自动机
    直接统计答案即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e6;
    int fa[maxn],c[maxn],tr[maxn][10],tot=0;
    int ins(char ch,int pos)
    {
        int id=ch-'a';
        if(!tr[pos][id])
        {
            tr[pos][id]=++tot;
            fa[tot]=pos;
            c[tot]=id;
        }
        return tr[pos][id];
    }
    #define Cpy(a, b) memcpy(a, b, sizeof(a))
    struct Suffix_Automata
    {
        int maxlen[maxn], trans[maxn][10], link[maxn], Size,pos[maxn];
        Suffix_Automata() { Size = 1; }
        inline int Extend(int id,int Last)
        {
            int cur = (++Size), p;
            maxlen[cur] = maxlen[Last] + 1;
            for (p = Last; p && !trans[p][id]; p = link[p])
                trans[p][id] = cur;
            if (!p)
                link[cur] = 1;
            else 
            {
                int q = trans[p][id];
                if (maxlen[q] == maxlen[p] + 1) 
                    link[cur] = q;
                else  
                {
                    int clone = (++Size);
                    maxlen[clone] = maxlen[p] + 1;
                    Cpy(trans[clone], trans[q]);
                    link[clone] = link[q];
                    for (; p && trans[p][id] == q; p = link[p])
                        trans[p][id] = clone;
                    link[cur] = link[q] = clone;
                }
            }
            return cur;
        }
        inline void build()
        {
            queue<int>q;
            for(int i=0;i<10;++i)
            {
                if(tr[0][i])
                    q.push(tr[0][i]);
            }
            pos[0]=1;
            while(!q.empty())
            {
                int x=q.front();q.pop();
                pos[x]=Extend(c[x],pos[fa[x]]);
                for(int i=0;i<10;++i)
                    if(tr[x][i])q.push(tr[x][i]);
            }
        }
        inline void cal(){
            ll ans=0;
            for(int i=2;i<=Size;++i)ans+=maxlen[i]-maxlen[link[i]];
            printf("%lld
    ",ans);
        }
    } sam;
    char s[maxn];
    int pre[maxn];
    int main()
    {
        scanf("%s",s+1);
        int len=strlen(s+1);
        for (int i = len; i >= 1; i--)
        {
            int p = 0;
            for (int j = i + 1; j <= len; j++)
            {
                if (s[i] > s[j]) s[j] = s[i];
                else
                {
                    p = j;
                    break;
                }
            }
            int sta;
            if (p == 0) sta = len;
            else sta = p - 1;
            pre[i] = pre[p];
            for (int j = sta; j >= i; j--) pre[i] = ins(s[i], pre[i]);
        }
        sam.build();
        sam.cal();
        return 0;
    }
    
  • 相关阅读:
    做好测试计划和测试用例的工作的关键是什么?
    windows创建虚拟环境
    面试题整理
    【爬虫】使用selenium设置cookie
    【爬虫】随机获取UA
    Scrapy爬虫提高效率
    【爬虫】多线程爬取糗事百科写入文件
    【爬虫】多线程爬取表情包
    【爬虫】Condition版的生产者和消费者模式
    【爬虫】Load版的生产者和消费者模式
  • 原文地址:https://www.cnblogs.com/Zeronera/p/13365089.html
Copyright © 2011-2022 走看看