• 【美团杯2020】半前缀计数(SAM)


    前言

    史上最通俗的后缀自动机详解:https://www.luogu.com.cn/blog/Kesdiael3/hou-zhui-zi-dong-ji-yang-xie

    题意

    设小写字母字符串(s),长度为(n)(s[l:r])表示第(l)个到第(r)个字符构成的子串。
    定义半前缀是(s[1:i]+s[j:k]),其中(0≤i<len(s),i<j≤len(s),j−1≤k≤len(s))。直观上来说,你可以把半前缀理解成某一个前缀(s[1:k])删除掉某一个子串后形成的结果(当然也允许不删)。
    给出字符串(s),你需要求出(s)的所有半前缀中,有多少个不同的字符串。

    思路

    对于一个半前缀(s[1:i]+s[j:k]),如果有(s[1:i+1]+s[j+1:k])与其相等即(s[i+1]=s[j])时,则说明这个半前缀重复了。因此,对于每个前缀(s[1:i]),我们统计(s[i+1:n])中有多少不同子串不以(s[i+1])开始,把这些加起来就是答案。我们将串倒序加入后缀自动机,这样我们就能够知道每次以(s[i])开始的子串数量。然后对于每个前缀统计答案即可。注意计算空串。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxx = 1e6+10;
    struct node
    {
        int ch[26];
        int len,fa;
        node(){memset(ch,0,sizeof(ch));len=0;}
    }dian[maxx];
    int las=1,tot=1;
    void add(int c)
    {
        int p=las;int np=las=++tot;
        dian[np].len=dian[p].len+1;
        for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np;
        if(!p)dian[np].fa=1;
        else
        {
            int q=dian[p].ch[c];
            if(dian[q].len==dian[p].len+1)dian[np].fa=q;
            else
            {
                int nq=++tot;dian[nq]=dian[q];
                dian[nq].len=dian[p].len+1;
                dian[q].fa=dian[np].fa=nq;
                for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;
            }
        }
    }
    char s[maxx];
    LL cnt[26];
    int main()
    {
        scanf("%s",s+1);
        int n=strlen(s+1);
        LL sum=1,ans=1;
        for(int i=n;i>=1;i--)
        {
            add(s[i]-'a');
            LL tmp=dian[las].len-dian[dian[las].fa].len;
            cnt[s[i]-'a']+=tmp;
            sum+=tmp;
            ans+=sum-cnt[s[i]-'a'];
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Servlet的生命周期?
    C++图结构的图结构操作示例
    如何从google play下载app应用,直接下载apk
    C# Socket异步聊天例子
    三极管饱和,放大,截止电压判断
    java中的浮点(float)运算
    微软2014校园招聘笔试试题
    软件开发中的资源控制问题学习
    linux mount命令学习
    17、Spring Boot普通类调用bean【从零开始学Spring Boot】
  • 原文地址:https://www.cnblogs.com/HooYing/p/12955955.html
Copyright © 2020-2023  润新知