• 后缀数组:


    1、差异:
    卡在两个地方。
    1是相等的值可能多算或者漏算。要手模一下。相等的不能简单覆盖,记在一个上面。x==y,idx<idy,L和id不同。y的L应该记为idx+1,
    否则会多算,重复。所以单调栈是<=。
    2是L,R的计算。(i-id[top])之前写的是i-id+1.
    性质:排名为 i, j(i < j) 的后缀的 lcp 为 min{height[k] | i + 1 ≤ k ≤ j}
    sigma(leni,j)=(n-1)*(n+1)*n/2. n-1是每一个都被算了n-1次。后面是前缀和。
    转换:求lcp。求heigh[i]成为最小值的区间。
        单调栈维护。小难点是相等的值要手模一下。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define F(i,a,b) for(register int i=a;i<=b;++i)
    #define forb(i,a,b) for(register int i=a;i>=b;--i)
    #define il inline
    #define LL long long
    #define rg register
    #define pf(a) printf("%d ",a)
    #define PF(a) printf("%lld ",a)
    #define phn puts("")
    using namespace std;
    int read();
    /*
    卡在两个地方。
    1是相等的值可能多算或者漏算。要手模一下。相等的不能简单覆盖,记在一个上面。x==y,idx<idy,L和id不同。y的L应该记为idx+1,
    否则会多算,重复。所以单调栈是<=。
    2是L,R的计算。(i-id[top])之前写的是i-id+1.
    性质:排名为 i, j(i < j) 的后缀的 lcp 为 min{height[k] | i + 1 ≤ k ≤ j}
    sigma(leni,j)=(n-1)*(n+1)*n/2. n-1是每一个都被算了n-1次。后面是前缀和。
    转换:求lcp。求heigh[i]成为最小值的区间。
        单调栈维护。小难点是相等的值要手模一下。
    */
    #define NX 500010
    int n,m;
    char str[NX];
    int a[NX],sa[NX],height[NX],rk[NX],tax[NX],tp[NX];
    void Rsort(){
        F(i,0,m)tax[i]=0;
        F(i,1,n)++tax[rk[tp[i]]];
        F(i,1,m)tax[i]+=tax[i-1];
        forb(i,n,1)sa[tax[rk[tp[i]]]--]=tp[i];
    }
    int cmp(int *f,int x,int y,int w){return f[x]==f[y]&&f[x+w]==f[y+w];}
    void Suffix(){
        F(i,1,n)rk[i]=a[i],tp[i]=i;
        m=127;Rsort();
        for(int w=1,p=1,i;p<n;w<<=1,m=p){
            for(p=0,i=n-w+1;i<=n;++i)tp[++p]=i;
            F(i,1,n)if(sa[i]>w)tp[++p]=sa[i]-w;
            Rsort();swap(rk,tp);rk[sa[1]]=p=1;
            F(i,2,n)rk[sa[i]]=cmp(tp,sa[i],sa[i-1],w)?p:++p;
        }
        int j,k=0;
        for(int i=1;i<=n;height[rk[i++]]=k)
            for(k=k?k-1:k,j=sa[rk[i]-1];a[i+k]==a[j+k];++k);
    }
    int sta[NX],id[NX],bg[NX],top;
    int main(){
        scanf("%s",str+1);
        n=strlen(str+1);
        F(i,1,n)a[i]=str[i];
        Suffix();
        LL ans=1ll*(n-1)*(n+1)*n/2;
      //  F(i,1,n)pf(rk[i]);phn;
      //  F(i,1,n)pf(height[i]);phn;
        height[n+1]=-1;
      //  PF(ans);
        F(i,1,n+1){
            while(top&&sta[top]>height[i]){
                ans-=2ll*(id[top]-bg[top])*(i-id[top])*sta[top--];//PF(ans);
            }
            if(!top){
                sta[++top]=height[i];id[top]=i;bg[top]=0;
            }
            else{
            //    if(sta[top]!=height[i]){
                   sta[++top]=height[i];id[top]=i;bg[top]=id[top-1];
            //    }
            }
        }
        printf("%lld",ans);
    }
    il int read(){
        rg int s=0,f=0;rg char ch;
        while(ch=getchar(),ch=='-'?f=1:0,ch<'0'||ch>'9');
        while(ch>='0'&&ch<='9'){
            s=s*10+(ch^48);ch=getchar();
        }
        return s;
    }
    /*
    g++ 1.cpp -g
    ./a.out
    eededeedeedeedde
    
    */
    View Code
    Informatik verbindet dich und mich. 信息将你我连结。
  • 相关阅读:
    org.apache.maven.archiver.MavenArchiver.getManifest
    网易云信发送短信验证码
    background-attachment:fixed;
    background-size属性100% cover contain
    width:100% width:auto 区别
    背景图全屏显示
    多行文字的垂直居中
    路径问题../绝对路径/
    用position子绝父相和css3动画,当鼠标一上去元素从底部慢慢向上
    前置后置运算符重载
  • 原文地址:https://www.cnblogs.com/seamtn/p/11297648.html
Copyright © 2020-2023  润新知