码迷,mamicode.com
首页 > 其他好文 > 详细

hiho#1445 重复旋律5 求子串数量 后缀自动机

时间:2019-04-06 23:10:25      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:clu   targe   nbsp   一个   har   理解   its   sig   can   

题目传送门

题意:给出一个字符串,求子串的个数。

思路:后缀自动机的题真是每做一题就更理解一些。

      SAM中的每一状态$p$都代表了一种子串,而p包含的字符串的个数是$len[p]-len[fa[p]]$,所以答案就是$sigma len[i]-len[fa[i]]$,还有答案要开long long。

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1000010;
char s[maxn];
int len[maxn<<1],ch[maxn<<1][27],fa[maxn<<1],tot=1,root=1,last=1,siz;
void extend(int x){
    int now=++tot,pre=last;
    last=now,len[now]=len[pre]+1;
    while( pre && !ch[pre][x]){
        ch[pre][x]=now;
        pre=fa[pre];
    }
    if(!pre)fa[now]=root;
    else{
        int q = ch[pre][x];
        if(len[q]==len[pre]+1)fa[now]=q;
        else {
            int nows=++tot;
            memcpy(ch[nows],ch[q],sizeof(ch[q]));
            len[nows]=len[pre]+1;
            fa[nows]=fa[q];
            fa[q]=fa[now]=nows;
            while(pre&&ch[pre][x]==q){
                ch[pre][x]=nows;
                pre=fa[pre];
            }
        }
    }
}

int main(){
    scanf("%s",s);
    siz=strlen(s);
    for(int i=0;i<siz;i++)
    {
        int p=s[i]-a;
        extend(p);
    }
    ll ans=0;
    for(int i=1;i<=tot;i++)
    {
        ans+=len[i]-len[fa[i]];
    }
    cout<<ans<<endl; 
}

 

hiho#1445 重复旋律5 求子串数量 后缀自动机

标签:clu   targe   nbsp   一个   har   理解   its   sig   can   

原文地址:https://www.cnblogs.com/mountaink/p/10663140.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!