ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P1117 [NOI2016]优秀的拆分

2019-02-18 22:42:50  阅读:313  来源: 互联网

标签:AA ch P1117 ++ luogu min NOI2016 l2 l1


传送门

这题居然暴力有95,,,

先考虑暴力,\(AABB\)显然可以看成两个相邻的\(AA\),记\(a_i\)为以i为结尾的\(AA\)个数,\(b_i\)为以i为结尾的\(AA\)个数,可以直接哈希统计每一种,答案为\(\sum_{i=1}^{n-1}a_ib_{i+1}\)

然后考虑优化统计答案,首先枚举一种长度\(l\in[1,\lfloor\frac{n}{2}\rfloor]\),然后每l位置放一个关键点,显然长度为\(2l\)的\(AA\)串会覆盖两个关键点,并且两个点在\(AA\)中的\(A\)出现位置相同

显然\(AA\)要满足\(min(lcs(i,j),l)+min(lcp(i,j),l)>l\),我们可以考虑利用这个条件,记\(l1=min(lcs(i,j),l),l2=min(lcp(i,j),l)\),那么可以知道\(s[i-l1+1,i+l2-1]=s[j-l1+1,j+l2-1]\),从而可以知道,在\(s[i-l1+1,i+l2-1]\)中任取长度为\(l\)的子串,这个子串后面一定接着一个一样的串,所以可以统计出左端点在\([i-l1+1,i+l2-l]\),长度为\(2l\)的\(AA\)串,所以a数组区间\([i-l1+l+l+1,i+l2+l]\)+1,b数组区间\([i-l1+1,i+l2-l]\)+1,差分统计即可

复杂度\(\sum_{i=1}^{\frac{n}{2}}\frac{n}{i}\),大约是\(nlogn\)

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register

using namespace std;
const int N=4e4+10;
il LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int sa[N],rr[N],rk[N],wx[N],wr[N],bk[N],he[N];
int mip[N][15],mis[N][15];
char cc[N];
int n,lz,aa[N],bb[N];
il void gSA(bool o)
{
    memset(wr,0,sizeof(wr));
    int sz=128;
    for(int i=0;i<=sz;++i) bk[i]=0;
    for(int i=1;i<=n;++i) ++bk[rk[i]=cc[i]];
    for(int i=1;i<=sz;++i) bk[i]+=bk[i-1];
    for(int i=n;i;--i) sa[bk[rk[i]]--]=i;
    int j=1,tp=0,p=0;
    while(p<n)
    {
        tp=0;
        for(int i=n-j+1;i<=n;++i) wx[++tp]=i;
        for(int i=1;i<=n;++i) if(sa[i]>j) wx[++tp]=sa[i]-j;
        for(int i=1;i<=n;++i) wr[i]=rk[wx[i]];
        for(int i=0;i<=sz;++i) bk[i]=0;
        for(int i=1;i<=n;++i) ++bk[wr[i]];
        for(int i=1;i<=sz;++i) bk[i]+=bk[i-1];
        for(int i=n;i;--i) sa[bk[wr[i]]--]=wx[i];
        for(int i=1;i<=n;++i) wr[i]=rk[i];
        rk[sa[1]]=p=1;
        for(int i=2;i<=n;++i) rk[sa[i]]=p+=(wr[sa[i]]==wr[sa[i-1]]&&wr[sa[i]+j]==wr[sa[i-1]+j])^1;
        sz=p,j<<=1;
    }
    for(int i=1;i<=n;++i) he[i]=0;
    for(int i=1;i<=n;++i)
    {
        if(he[rk[i-1]]) he[rk[i]]=he[rk[i-1]]-1;
        int j=sa[rk[i]-1];
        while(cc[i+he[rk[i]]]==cc[j+he[rk[i]]]) ++he[rk[i]];
    }
    int mi[N][15];
    memset(mi,0,sizeof(mi));
    for(int i=1;i<=n;++i) mi[i][0]=he[i];
    for(int j=1;j<=lz;++j)
    {
        for(int i=1;i<=n;++i)
            mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
    }
    o?memcpy(mip,mi,sizeof(mi)):memcpy(mis,mi,sizeof(mi));
}
il int lcp(int i,int j)
{
    i=rr[i],j=rr[j];
    if(i==j) return -n;
    if(i>j) swap(i,j);
    ++i;
    int l=log2(j-i+1);
    return min(mip[i][l],mip[j-(1<<l)+1][l]);
}
il int lcs(int i,int j)
{
    i=rk[n-i+1],j=rk[n-j+1];
    if(i==j) return -n;
    if(i>j) swap(i,j);
    ++i;
    int l=log2(j-i+1);
    return min(mis[i][l],mis[j-(1<<l)+1][l]);
}

int main()
{
    int T=rd();
    while(T--)
    {
        memset(aa,0,sizeof(aa));
        memset(bb,0,sizeof(bb));
        scanf("%s",cc+1);
        n=strlen(cc+1),lz=log2(n);
        gSA(1);
        memcpy(rr,rk,sizeof(rk));
        for(int i=1;i<=n/2;++i) swap(cc[i],cc[n-i+1]);
        gSA(0);
        for(int l=1;l<=n/2;++l)
            for(int i=1,j=l+1;j<=n;i+=l,j+=l)
            {
                int l1=min(lcs(i,j),l),l2=min(lcp(i,j),l);
                if(l1+l2>l)
                {
                    ++aa[i-l1+1+l+l-1],--aa[i+l2+l];
                    ++bb[i-l1+1],--bb[i+l2-l+1];
                }
            }
        for(int i=1;i<=n;++i) aa[i]+=aa[i-1],bb[i]+=bb[i-1];
        LL ans=0;
        for(int i=1;i<n;++i) ans+=1ll*aa[i]*bb[i+1];
        printf("%lld\n",ans);
    }
    return 0;
}

沙雕\(nlog^2n\)做法

标签:AA,ch,P1117,++,luogu,min,NOI2016,l2,l1
来源: https://www.cnblogs.com/smyjr/p/10398349.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有