• P4248 [AHOI2013]差异


    思路

    SAM
    后缀自动机parent树的LCA就是两个子串的最长公共后缀
    现在要求LCP
    所以把字符串反转一下
    然后每个点的贡献就是endpos的大小,dfs一遍求出贡献就可以了

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    const int MAXN = 500500*2; 
    int Nodecnt,trans[MAXN][26],suflink[MAXN],endpos[MAXN],maxlen[MAXN],fir[MAXN],nxt[MAXN],v[MAXN],cnt,ans,n;
    char s[MAXN];
    int sum(int l,int r){
        if(r<l)
            return 0;
        return (r+l)*(r-l+1)/2;    
    }
    void addedge(int ui,int vi){
        ++cnt;
        v[cnt]=vi;
        nxt[cnt]=fir[ui];
        fir[ui]=cnt;
    }
    int New_state(int _maxlen,int *_trans,int _suflink){
        int o=++Nodecnt;
        maxlen[o]=_maxlen;
        suflink[o]=_suflink;
        if(_trans){
            for(int i=0;i<26;i++)
                trans[o][i]=_trans[i];
        }
        return o;
    }
    int add_len(int u,int c){
        int z=New_state(maxlen[u]+1,NULL,0);
        endpos[z]=1;
        while(u&&(trans[u][c]==0)){
            trans[u][c]=z;
            u=suflink[u];
        }
        if(!u){
            suflink[z]=1;
            return z;
        }
        int v=trans[u][c];
        if(maxlen[u]+1==maxlen[v]){
            suflink[z]=v;
            return z;
        }
        int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
        suflink[z]=suflink[v]=y;
        while(u&&trans[u][c]==v){
            trans[u][c]=y;
            u=suflink[u];
        }
        return z;
    }
    void dfs(int x){
        for(int i=fir[x];i;i=nxt[i]){
            dfs(v[i]);
            ans-=endpos[v[i]]*endpos[x]*maxlen[x]*2;
            endpos[x]+=endpos[v[i]];
        }
    }
    signed main(){
        scanf("%s",s+1);
        n=strlen(s+1); 
        reverse(s+1,s+n+1);
        Nodecnt=1;
        int last=1;
        for(int i=1;i<=n;i++)
            last=add_len(last,s[i]-'a');
        for(int i=1;i<=n;i++){
            int j=i+1;
            ans+=(n-i+1)*(n-j+1)+sum(1,n-j+1);
        }
        for(int i=2;i<=Nodecnt;i++)
            addedge(suflink[i],i);
        dfs(1);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Android 目前最稳定和高效的UI适配方案
    很值得收藏的安卓开源控件库
    django-初始配置(纯手写)
    面向对象 继承
    wsgiref手写一个web服务端
    socket手写一个简单的web服务端
    vue指令
    vue入门
    python中and,or
    面向对象三大特性-继承
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10634414.html
Copyright © 2020-2023  润新知