zoukankan      html  css  js  c++  java
  • bzoj 4650: [Noi2016]优秀的拆分

    传送门

    随便后缀数组跑一跑n^2就有95分,简直不能再划算啊。

    正解如图。然后差分就好了。

    灵魂画手。

    这两天bug奇多,难得1A,老泪纵横。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<ctime>
    const int N=100007;
    typedef long long LL;
    using namespace std;
    int T,n,sa1[N],sa2[N],h1[N][20],h2[N][20],rak1[N],rak2[N],cl[N],cr[N],cc1[N],cc2[N];
    char s[N];
    
    template<typename T> void read(T &x) {
        T f=1; x=0; char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int cmp(int a,int b,int k,int y[]) {
        int o1=a+k>=n?-1:y[a+k];
        int o2=b+k>=n?-1:y[b+k];
        return (o1==o2)&&(y[a]==y[b]); 
    }
    
    void make_hight(int sa[],int h[][20],int rank[]) {
        for(int i=0;i<n;i++) rank[sa[i]]=i;
        for(int i=0,k=0;i<n;i++) {
            if(!rank[i]) continue;
            if(k) k--;
            int j=sa[rank[i]-1];
            while(s[i+k]==s[j+k]) k++;
            h[rank[i]-1][0]=k;
        }
        for(int j=1;j<20;j++)     
            for(int i=0;i+(1<<j-1)<n;i++) 
                h[i][j]=min(h[i][j-1],h[i+(1<<j-1)][j-1]);
    }
    
    void make_sa(int sa[],int h[][20],int rank[]) {
        static int t1[N],t2[N],c[N];
        int *x=t1,*y=t2,i,k,m='z'+1;
        for(i=0;i<m;i++) c[i]=0;
        for(i=0;i<n;i++) c[x[i]=s[i]]++;
        for(i=1;i<m;i++) c[i]+=c[i-1];
        for(i=0;i<n;i++) sa[--c[x[i]]]=i;
        for(k=1;k<=n;k<<=1) {
            int p=0;
            for(i=n-k;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 
            for(i=0;i<m;i++) c[i]=0;
            for(i=0;i<n;i++) c[x[y[i]]]++;
            for(i=1;i<m;i++) c[i]+=c[i-1];
            for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
            swap(x,y); p=1; x[sa[0]]=0;
            for(i=1;i<n;i++) 
                x[sa[i]]=cmp(sa[i-1],sa[i],k,y)?p-1:p++;
            if(p>=n) break;
            m=p;
        }
        make_hight(sa,h,rank);
    }
    
    int get_lcp(int l,int r,int h[][20],int rank[]) {
        l=rank[l]; r=rank[r]; if(l>r) swap(l,r);
        int k=0;
        while(l+(1<<k)<=r) k++; k--;
        return min(h[l][k],h[r-(1<<k)][k]);
    } 
    
    void clear() {
        memset(cc1,0,sizeof(cc1));
        memset(cc2,0,sizeof(cc2));
    }
    
    int main() {
        read(T);
        while(T--) {
            scanf("%s",s);
            n=strlen(s);
            make_sa(sa1,h1,rak1);
            for(int i=0;i<n/2;i++) swap(s[i],s[n-i-1]);
            make_sa(sa2,h2,rak2);
            for(int l=1;l<=n/2;l++) 
                for(int i=l;i<n;i+=l) {
                    int j=i+l;
                    int x=j>=n?0:min(l-1,get_lcp(i,j,h1,rak1)); 
                    int y=j-1>=n?0:min(l,get_lcp(n-i,n-j,h2,rak2));
                    if(x+y<l) continue;
                    cc1[i-y]+=1; cc1[i+x-l+1]-=1;
                    cc2[i-y+2*l-1]+=1; cc2[i+x-l+1+2*l-1]-=1;
                }
            int sum1=0,sum2=0; 
            for(int i=0;i<n;i++) {
                sum1+=cc1[i]; sum2+=cc2[i];
                cl[i]=sum1; cr[i]=sum2; 
            }
            LL ans=0;
            for(int i=0;i+1<n;i++) 
                ans+=(LL)cr[i]*cl[i+1];
            printf("%lld
    ",ans);
            if(T) clear();
        } 
        return 0;
    }
    /*
    1
    aabaabaabaa
    */
    View Code
  • 相关阅读:
    为什么我们不要 .NET 程序员
    Jquery异步请求数据实例代码
    关系数据库中表的基本属性有哪些
    利用VC从DLL传递消息到EXE
    新实体与原实体之间为一对多关系
    本人C++ Builder开发的仿Windows桌面应用程序源码
    delphi窗体动态设计 在系统运行时动态更改控件属性
    DB.ASP 用Javascript写ASP很灵活很好用很easy
    CrazyScan Satellite scan software 卫星扫描
    delphi中窗体半透明效果如何实现
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8343909.html
Copyright © 2011-2022 走看看