【后缀自动机】BZOJ5084[hashit]题解

题目概述

给出一个操作串:如果是小写字母,表示在当前字符串后面添加这个小写字母。如果是 <script type="math/tex" id="MathJax-Element-1">-</script> ,表示删除当前字符串最后的小写字母(保证合法)。求每次操作后当前字符串不同子串的个数。

解题报告

不同子串个数是后缀自动机裸题,由于每次只删除最后一个小写字母,所以瞎搞就行了……

2018.5.20UPD:这样复杂度是不对的,正解是后缀平衡树,不过没故意卡还是过了XD。

好像也可以后缀平衡树?但是我不会QAQ。

示例程序

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fr first
#define sc second
#define mp make_pair
using namespace std;
typedef long long LL;
const int maxl=100000,maxt=maxl<<1,maxi=26;

int si,ro,p,son[maxt+5][maxi],fa[maxt+5],MAX[maxt+5];LL ans,v[maxl+5];
int now,A[maxl+5],B[maxl+5],P[maxl+5],pos;pair<int*,int> tem[maxt+5];

#define newnode(m) (A[now]++,fa[++si]=0,MAX[si]=m,memset(son[si],0,sizeof(son[si])),si)
#define val(p) (MAX[p]-MAX[fa[p]])
#define Add(x) (tem[++pos]=mp(&x,x),B[now]++)
inline void Extend(int w){
    now++;A[now]=B[now]=v[now]=0;P[now]=p;
    int np=newnode(MAX[p]+1);while (p&&!son[p][w]) Add(son[p][w]),son[p][w]=np,p=fa[p];
    if (!p) fa[np]=ro; else{
        int q=son[p][w];
        if (MAX[p]+1==MAX[q]) fa[np]=q; else{
            int nq=newnode(MAX[p]+1);memcpy(son[nq],son[q],sizeof(son[q]));
            v[now]-=val(q);fa[nq]=fa[q];v[now]+=val(nq);
            Add(fa[q]);fa[np]=fa[q]=nq;v[now]+=val(q);
            while (p&&son[p][w]==q) Add(son[p][w]),son[p][w]=nq,p=fa[p];
        }
    }
    v[now]+=val(np);ans+=v[now];p=np;
}
int main(){
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);
    for (char ch=(p=ro=newnode(0),getchar());'a'<=ch&&ch<='z'||ch=='-';ch=getchar()){
        if ('a'<=ch&&ch<='z') Extend(ch-'a'); else{
            for (int i=1;i<=B[now];i++,pos--) *tem[pos].fr=tem[pos].sc;
            si-=A[now];ans-=v[now];p=P[now];now--;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值