BZOJ4650 [Noi2016]優れたスプリット

質問の意味:

数回に分割し、各サブ文字列のクエリ文字列\(AABB \)式の合計。

知識ポイント:

接尾辞配列は、違い、考え方のアイデアを調整します

ソリューション:

\([]、B [ ] \)は、 それぞれの現在の開始と終了である\(AA \) 次いで数スキーム列、全て\(b_i \ {I A_回 + 1} \) と答えています。などから、キーポイントに考えて、良好な需要の長さを制限することが求めているので、(1 \)\\(\ FRAC {n}は{ 2} \) キーポイントは各ことで設定した\(LEN \)位置ポイントは、次に隣接する\(2 \)は回答のキーポイントを求めている貢献しました。

具体的には、隣接する二つのキーポイントの\(I \)\(J \)、\ (I \)\(J \)をそれぞれ前方、後方以上は超えないように共通部分(音符を探し出します\(LEN-1 \)バック超えない\(LEN \) それ以外の場合は)寄与を計算繰り返される、もし\(LCS \)\(LCP \)未満\(LEN \)は、肯定ない繰り返し部が存在しないこと解決策はありません。そうでない場合は、右端期間の終了する期間の初め左端にし、その時点で左のその部分を繰り返します。それをクリックし、差動。

備考:

注:1、SAをパッケージ化する必要があります。2、この質問は検討に値する内容をたくさん持っています。3、明らかに十分なこのブログの図:https://gypsophila.blog.luogu.org/solution-p1117

コード:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long ll;
const int maxn=300010;
ll ans,a[maxn],b[maxn];
int n,T,mlog[maxn];

struct SA
{
    char s[maxn];
    int m,sa[maxn],rnk[maxn],height[maxn],c[maxn],y[maxn],f[20][maxn];
    
    void clear()
    {
        m=26;
        memset(f,0x3f,sizeof(f));
        for (register int i=0;i<=n+5;i++)
            sa[i]=rnk[i]=height[i]=y[i]=0;
    }
    
    void rsort()
    {
        int i;
        for (i=0;i<=m+1;i++)
            c[i]=0;
        for (i=1;i<=n;i++)
            c[rnk[i]]++;
        for (i=2;i<=m;i++)
            c[i]+=c[i-1];
        for (i=n;i>=1;i--)
            sa[c[rnk[y[i]]]--]=y[i],y[i]=0;
    }
    
    void getsa()
    {
        int i,k,p=0;
        for (i=1;i<=n;i++)
            rnk[i]=s[i]-'a'+1,y[i]=i;
        rsort();
        for (k=1;k<n&&p<n;k<<=1,m=p)
        {
            p=0;
            for (i=n-k+1;i<=n;i++)
                y[++p]=i;
            for (i=1;i<=n;i++)
                if (sa[i]>k)
                    y[++p]=sa[i]-k;
            rsort();
            swap(rnk,y);
            rnk[sa[p=1]]=1;
            for (i=2;i<=n;i++)
                rnk[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?p:(++p);
        }
    }
    
    void getheight()
    {
        int i,j,k=0;
        for (i=1;i<=n;i++)
        {
            if (rnk[i]==1)
                continue;
            if (k)
                k--;
            j=sa[rnk[i]-1];
            while (i+k<=n&&j+k<=n&&s[i+k]==s[j+k])
                k++;
            height[rnk[i]]=k;
        }
    }
    
    void init()
    {
        int i,j;
        for (i=1;i<=n;i++)
            f[0][i]=height[i];
        for (j=1;(1<<j)<=n;j++)
            for (i=1;i+(1<<j)-1<=n;i++)
                f[j][i]=min(f[j-1][i],f[j-1][i+(1<<(j-1))]);
    }
    
    int rmq(int l,int r)
    {
        int k=mlog[r-l+1];
        return min(f[k][l],f[k][r-(1<<k)+1]);
    }
}A,B;

int LCP(int i,int j)
{
    i=A.rnk[i],j=A.rnk[j];
    if (i>j)
        swap(i,j);
    i++;
    return A.rmq(i,j);
}

int LCS(int i,int j)
{
    i=n+1-i,j=n+1-j;
    i=B.rnk[i],j=B.rnk[j];
    if (i>j)
        swap(i,j);
    i++;
    return B.rmq(i,j);
}

int main()
{
    int i,j,len,lcs,lcp,Len;
    scanf("%d",&T);
    for (i=2;i<=300000;i++)
        mlog[i]=mlog[i>>1]+1;
    while (T--)
    {
        scanf("%s",A.s+1);
        n=strlen(A.s+1);
        A.clear(),B.clear();
        ans=0;
        for (i=0;i<=n+1;i++)
            a[i]=b[i]=0;
        for (i=1;i<=n;i++)
            B.s[i]=A.s[n+1-i];
        A.getsa();
        B.getsa();
        A.getheight();
        B.getheight();
        A.init();
        B.init();
        for (len=1;len<=(n>>1);len++)
            for (i=len,j=i+len;j<=n;i+=len,j+=len)
                if (A.s[i]==A.s[j])
                {
                    lcp=min(len,LCP(i,j)),lcs=min(len-1,LCS(i-1,j-1));
                    if (lcp+lcs>=len)
                    {
                        Len=lcs+lcp-len+1;
                        a[i-lcs]++,a[i-lcs+Len]--;
                        b[j+lcp-Len]++,b[j+lcp]--;
                    }
                }
        for (i=1;i<=n;i++)
            a[i]+=a[i-1],b[i]+=b[i-1];
        for (i=1;i<=n-1;i++)
            ans+=1ll*b[i]*a[i+1];
        printf("%lld\n",ans);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/Ronald-MOK1426/p/12294541.html