[SAM] hihoCoder1445 后缀自动机二·重复旋律5

题意

给出一个只含小写字母的串 s ,求 s 的不同的子串总数。
|s|1000000

题解

SAM 最水的模板题。
直接建出 SAM ,把所有状态的 max(A)min(A)+1 全部加起来即是答案。应该不需要解释。
实现的话可以在 Extend 过程中维护,这样写比较有价值,最后扫一趟太丑啦…

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000005;
struct node{
    node *par,*ch[26]; int _max;
    node(int t1=0){ _max=t1; par=0; memset(ch,0,sizeof(ch)); }
    int cnt(){ return _max-par->_max; }
} *root, *last;
typedef node* P_node;
long long ans;
void Extend(char x){
    P_node p=last, np=new node(p->_max+1);
    while(p&&p->ch[x]==0) p->ch[x]=np, p=p->par;
    if(!p) np->par=root; else{
        P_node q=p->ch[x]; 
        if(q->_max==p->_max+1) np->par=q; else{
            P_node nq=new node(p->_max+1);
            memcpy(nq->ch,q->ch,sizeof(q->ch));
            ans-=q->cnt(); //*
            nq->par=q->par; q->par=nq; np->par=nq;
            ans+=q->cnt()+nq->cnt(); //*
            while(p&&p->ch[x]==q) p->ch[x]=nq, p=p->par;
        }
    }
    ans+=np->cnt(); //*
    last=np;
}
char s[maxn];
int n;
int main(){
    freopen("hiho1445.in","r",stdin);
    freopen("hiho1445.out","w",stdout);
    scanf("%s",s+1); n=strlen(s+1);
    root=last=new node(0);
    for(int i=1;i<=n;i++) Extend(s[i]-'a');
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值