luogu P4248 [AHOI2013] SAM difference

luogu P4248 [AHOI2013] Difference

link

luogu

Thinking

\ (\ SUM \ {limits_. 1 <= I <J <= n-len {} {} (T_i)} + {len (T_j) -2 LCP} * {(T_i, T_j)} \)
= \ (\ SUM \ limits_ {1 <= i < j <= n} {{len} (T_i) + {len} (T_j)} - \ sum \ limits_ {1 <= i <j <= n} 2 * {lcp} ( t_i, T_j) \)
the first part is \ (\ frac {n * (
n + 1) (n-1)} {2} \) the second half of the parent tree determined by sam siz solving process on the line.
Lcp two strings is the longest of their lca.
Consider the contribution within the sub-tree on the line.

Code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+7;
int n,c[N<<1],a[N<<1];
char s[N];
struct sam {
    int len,fa,ch[26];
}dian[N<<1];
int siz[N<<1],las=1,tot=1;
void add(int c,int k_th) {
    int p=las;int np=las=++tot;
    dian[np].len=dian[p].len+1;
    for(;p&&!dian[p].ch[c];p=dian[p].fa) dian[p].ch[c]=np;
    if(!p) dian[np].fa=1;
    else {
        int q=dian[p].ch[c];
        if(dian[q].len==dian[p].len+1) dian[np].fa=q;
        else {
            int nq=++tot;
            dian[nq]=dian[q];
            dian[nq].len=dian[p].len+1;
            dian[q].fa=dian[np].fa=nq;
            for(;p&&dian[p].ch[c]==q;p=dian[p].fa)
                dian[p].ch[c]=nq;
        }
    }
    siz[las]=1;
}
signed main() {
    scanf("%s",s+1);
    n=strlen(s+1);
    for(int i=n;i>=1;--i) add(s[i]-'a',i);
    for(int i=1;i<=tot;++i) c[dian[i].len]++;
    for(int i=1;i<=tot;++i) c[i]+=c[i-1];
    for(int i=1;i<=tot;++i) a[c[dian[i].len]--]=i;
    int ans=1LL*n*(n+1)*(n-1)/2;
    for(int i=tot;i>=1;--i) {
        ans-=2LL*siz[a[i]]*siz[dian[a[i]].fa]*dian[dian[a[i]].fa].len;
        siz[dian[a[i]].fa]+=siz[a[i]];  
    }
    printf("%lld",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/dsrdsr/p/11183030.html