HIHOcoder 1445 后缀自动机二·重复旋律5

Posted dreagonm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HIHOcoder 1445 后缀自动机二·重复旋律5相关的知识,希望对你有一定的参考价值。

思路

题目要求求出有多少个不同的子串出现

因为后缀自动机每个状态存储的是连续的后缀,所以一个状态对应的子串个数就是maxlen[x]-minlen[x]+1

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 1000100*2;
int maxlen[MAXN],minlen[MAXN],trans[MAXN][26],suflink[MAXN],cnt=0,n=0;
char s[MAXN];
int new_st(int _maxlen,int _minlen,int *_trans,int _suflink){
    ++cnt;
    maxlen[cnt]=_maxlen;
    minlen[cnt]=_minlen;
    if(_trans)
        for(int i=0;i<26;i++)
            trans[cnt][i]=_trans[i];
    suflink[cnt]=_suflink;
    return cnt;
}
int add_len(int u,int c){
    int z=new_st(maxlen[u]+1,0,NULL,0);
    while(u&&(!trans[u][c])){
        trans[u][c]=z;
        u=suflink[u];
    }
    if(u==0){
        suflink[z]=1;
        minlen[z]=1;
        return z;
    }
    int v=trans[u][c];
    if(maxlen[u]+1==maxlen[v]){
        suflink[z]=v;
        minlen[z]=maxlen[v]+1;
        return z;
    }
    int y=new_st(maxlen[u]+1,0,trans[v],suflink[v]);
    suflink[v]=suflink[z]=y;
    minlen[v]=minlen[z]=maxlen[y]+1;
    while(u&&trans[u][c]==v){
        trans[u][c]=y;
        u=suflink[u];
    }
    minlen[y]=maxlen[suflink[y]]+1;
    return z;
}
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    int pre=1;
    cnt=1;
    long long ans=0;
    for(int i=1;i<=n;i++)
        pre=add_len(pre,s[i]-'a');
    for(int i=2;i<=cnt;i++){
        ans+=maxlen[i]-minlen[i]+1;
        // printf("%d %d %d %d
",i,suflink[i],minlen[i],maxlen[i]);
    }
    printf("%lld
",ans);
    return 0;
}

以上是关于HIHOcoder 1445 后缀自动机二·重复旋律5的主要内容,如果未能解决你的问题,请参考以下文章

HihoCoder1445 后缀自动机二·重复旋律5

HihoCoder - 1445 后缀自动机 试水题

后缀自动机专题(hihocoder)

hihocoder 后缀自动机二·重复旋律5

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

求不同的子串种类