zoukankan      html  css  js  c++  java
  • BZOJ 4566 [Haoi2016]找相同字符 ——广义后缀自动机

    建立广义后缀自动机。

    然后统计子树中的siz,需要分开统计

    然后对(l[i]-l[fa[i]])*siz[i][0]*siz[i][1]求和即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define maxn 800005
     
    struct Suffix_Auto{
        int go[maxn][26],l[maxn],siz[maxn],fa[maxn];
        int last,cnt,v[maxn],q[maxn],rit[maxn][2];
        char s[maxn];
        void init()
        {
            last=cnt=1;
            memset(go,0,sizeof go);
        }
        void add(int x,int id)
        {
            int p=last,q;
            if (q=go[p][x])
            {
                if (l[q]==l[p]+1) last=q;
                else
                {
                    int nq=++cnt;
                    l[nq]=l[p]+1;
                    memcpy(go[nq],go[q],sizeof go[q]);
                    fa[nq]=fa[q];
                    fa[q]=nq;
                    for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    last=nq;
                }
            }
            else
            {
                int np=++cnt; l[np]=l[p]+1;
                for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
                if (!p) fa[np]=1;
                else
                {
                    q=go[p][x];
                    if (l[q]==l[p]+1) fa[np]=q;
                    else
                    {
                        int nq=++cnt;
                        l[nq]=l[p]+1;
                        memcpy(go[nq],go[q],sizeof go[q]);
                        fa[nq]=fa[q];
                        fa[q]=fa[np]=nq;
                        for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    }
                }
                last=np;
            }
            rit[last][id]++;
        }
        void build()
        {
            int n1;
            init();
            scanf("%s",s+1);
            n1=strlen(s+1);
            F(i,1,n1) add(s[i]-'a',0);
            last=1;
            scanf("%s",s+1);
            n1=strlen(s+1);
            F(i,1,n1) add(s[i]-'a',1);
        }
        void radix()
        {
            F(i,1,cnt) v[l[i]]++;
            F(i,1,cnt) v[i]+=v[i-1];
            D(i,cnt,1) q[v[l[i]]--]=i;
            D(i,cnt,1)
            {
                rit[fa[q[i]]][0]+=rit[q[i]][0];
                rit[fa[q[i]]][1]+=rit[q[i]][1];
            }
            ll ans=0;
            F(i,1,cnt)
                ans+=(ll)rit[i][0]*rit[i][1]*(l[i]-l[fa[i]]);
            printf("%lld
    ",ans);
        }
        void solve()
        {
            build();
            radix();
        }
    }sam;
     
    int main(){sam.solve();}
    

      

  • 相关阅读:
    js history对象 手机物理返回键
    正则表达式学习整理
    js获得时间new Date()整理
    币值转换
    打印沙漏
    秋季总结
    对我影响最大的三位老师
    我就是我
    秋季学期学习总结
    自我介绍
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6486869.html
Copyright © 2011-2022 走看看