【Codechef TASTR]違いのレベル - 接尾辞配列、および除外

差の[Codechef TASTR]レベル

説明

二つの文字列の異なる性質を考えると、正確に文字列による文字列の数に起こる求めます。

解決

セット\(U(S)は、\)を表す\(S \)は、その後の回答セット、サブセットを異なる性質に表示されます\(\)

\ [A = U(P)+ U(Q) - 2 U(P)\キャップU(Q)\]

\ [| A | = | U(P)| + | U(Q)| - 2 | U(P)\キャップU(Q)| \]

インクルージョン排除の原則によると、

\ [U(P)\キャップU(Q)= U(P)+ U(Q) - U(P)\カップU(Q)\]

それから

\ [| A | = 2 | U(P)\カップU(Q)| - U(P) - U(Q)\]

#include <bits/stdc++.h>
using namespace std;
#define int long long
struct sa
{
    int n,m=256,sa[1000005],y[1000005],u[1000005],v[1000005],o[1000005],r[1000005],h[1000005],T;
    char str[1000005];
    long long ans;

    int cal()
    {
        memset(sa,0,sizeof sa);
        memset(y,0,sizeof y);
        memset(u,0,sizeof u);
        memset(v,0,sizeof v);
        memset(o,0,sizeof o);
        memset(r,0,sizeof r);
        memset(h,0,sizeof h);

        n=strlen(str+1);

        for(int i=1; i<=n; i++) u[str[i]]++;
        for(int i=1; i<=m; i++) u[i]+=u[i-1];
        for(int i=n; i>=1; i--) sa[u[str[i]]--]=i;
        r[sa[1]]=1;
        for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);

        for(int l=1; r[sa[n]]<n; l<<=1)
        {
            memset(u,0,sizeof u);
            memset(v,0,sizeof v);
            memcpy(o,r,sizeof r);
            for(int i=1; i<=n; i++) u[r[i]]++, v[r[i+l]]++;
            for(int i=1; i<=n; i++) u[i]+=u[i-1], v[i]+=v[i-1];
            for(int i=n; i>=1; i--) y[v[r[i+l]]--]=i;
            for(int i=n; i>=1; i--) sa[u[r[y[i]]]--]=y[i];
            r[sa[1]]=1;
            for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
        }
        {
            int i,j,k=0;
            for(int i=1; i<=n; h[r[i++]]=k)
                for(k?k--:0,j=sa[r[i]-1]; str[i+k]==str[j+k]; k++);
        }

        ans=(long long)n*(long long)(n+1)/(long long)2;
        for(int i=1; i<=n; i++) ans-=(long long)h[i];

        return ans;
    }
} sa1,sa2,sa3;

char s1[1000005],s2[1000005];
int l1,l2;

signed main()
{
    scanf("%s",s1+1);
    scanf("%s",s2+1);
    l1=strlen(s1+1);
    l2=strlen(s2+1);
    memcpy(sa1.str,s1,sizeof s1);
    memcpy(sa2.str,s2,sizeof s2);
    for(int i=1; i<=l1; i++) sa3.str[i]=s1[i];
    sa3.str[l1+1]='$';
    for(int i=1; i<=l2; i++) sa3.str[i+l1+1]=s2[i];
    cout<<2ll*(sa3.cal()-(l1+1)*(l2+1))-sa1.cal()-sa2.cal()<<endl;
}

おすすめ

転載: www.cnblogs.com/mollnn/p/11775259.html