BZOJ2534: Uva10829L-gap字符串

http://www.lydsy.com/JudgeOnline/problem.php?id=2534

  给定字符串S,求形式为ABA的子串个数,其中B的长度为L。

  考虑A的两个起始位置x,y(x<y),应该满足如下两个条件:

    1.y>x+L

    2.LCP(x,y)≥y-x-L

  我们按height从大到小枚举,这样LCP就是变成了当前的height,将两个集合统计答案并合并。统计答案时枚举size较小的集合内的点作为x或y即可。可以用平衡树或者主席树来维护。

#include<bits/stdc++.h>
using namespace std;
const int maxn=50015;
typedef long long int64;
typedef pair<int,int> PII;
int n,l,cnt,q[maxn];
int64 ans;char s[maxn];
struct Tsplay{
    int tot;
    static const int maxnode=1000015;
    struct Tnode{
        Tnode *f,*c[2];int n,siz,val;
        void update(){siz=c[0]->siz+c[1]->siz+1;}
        void link(Tnode *newf,int newn){n=newn;f=newf;if (n!=2) f->c[n]=this;}
    }T[maxnode],*root[maxn],*null;
    void clear(){
        tot=0;null=T;null->c[0]=null->c[1]=null;null->siz=0;
        for (int i=1;i<=n;++i) root[i]=null;
    }
    Tnode *newnode(int v){
        Tnode *cur=T+(++tot);
        cur->f=cur->c[0]=cur->c[1]=null;
        cur->n=2;cur->val=v;cur->siz=1;
        return cur;
    }
    void rotate(Tnode *x){
        Tnode *y=x->f,*z=y->f;int nx=x->n,ny=y->n;
        x->link(z,ny);x->c[!nx]->link(y,nx);y->link(x,!nx);
        y->update();
    }
    void splay(int p,Tnode *x){
        while (x->n!=2){
            x->n==x->f->n?rotate(x->f):rotate(x);
            if (x->n!=2) rotate(x);
        }
        root[p]=x;x->update();
    }
    void insert(int p,int val){
        Tnode *x=root[p];
        if (x==null){root[p]=newnode(val);return;}
        while (1){
            if (val<x->val){
                if (x->c[0]==null){x->c[0]=newnode(val);x->c[0]->link(x,0);splay(p,x->c[0]);return;}
                else x=x->c[0];
            }
            else{
                if (x->c[1]==null){x->c[1]=newnode(val);x->c[1]->link(x,1);splay(p,x->c[1]);return;}
                else x=x->c[1];
            }
        }
    }
    int greater(int p,int v){
        Tnode *res=null,*x=root[p];
        while (x!=null){
            if (x->val>v){res=x;x=x->c[0];}
            else x=x->c[1];
        }
        if (res==null) return 0;
        else{splay(p,res);return res->c[1]->siz+1;}
    }
    int less(int p,int v){
        Tnode *res=null,*x=root[p];
        while (x!=null){
            if (x->val<v){res=x;x=x->c[1];}
            else x=x->c[0];
        }
        if (res==null) return 0;
        else{splay(p,res);return res->c[0]->siz+1;}
    }
    void travel(Tnode *x){
        if (x!=null) q[++cnt]=x->val;else return;
        travel(x->c[0]);travel(x->c[1]);
    }
    int size(int p){return root[p]->siz;}
    void travel(int x){cnt=0;travel(root[x]);}
    void merge(int t1,int t2){
        travel(t2);
        for (int i=1;i<=cnt;++i) insert(t1,q[i]);
    }
}splay;
struct Tsuffix_array{
    int sum[maxn],sa[maxn],rank[maxn],tsa[maxn],trank[maxn];
    bool cmp(int i,int j,int l){
        if (i+l>n||j+l>n) return 0;
        return rank[i]==rank[j]&&rank[i+l]==rank[j+l];
    }
    void suffix_sort(){
        int m=255,p,i,j;
        for (i=0;i<=m;++i) sum[i]=0;
        for (i=1;i<=n;++i) ++sum[rank[i]=s[i]];
        for (i=1;i<=m;++i) sum[i]+=sum[i-1];
        for (i=n;i>=1;--i) sa[sum[rank[i]]--]=i;
        for (p=0,j=1;p<n;j<<=1,m=p){
            for (p=0,i=n-j+1;i<=n;++i) tsa[++p]=i;
            for (i=1;i<=n;++i) if (sa[i]>j) tsa[++p]=sa[i]-j;
            for (i=0;i<=m;++i) sum[i]=0;
            for (i=1;i<=n;++i) ++sum[rank[tsa[i]]];
            for (i=1;i<=m;++i) sum[i]+=sum[i-1];
            for (i=n;i>=1;--i) sa[sum[rank[tsa[i]]]--]=tsa[i];
            for (p=trank[sa[1]]=1,i=2;i<=n;++i) trank[sa[i]]=cmp(sa[i],sa[i-1],j)?p:++p;
            memcpy(rank,trank,sizeof(int)*(n+1));
        }
    }
    int height[maxn];
    void get_height(){
        for (int h=0,i=1;i<=n;++i){
            if (rank[i]==1) continue;
            for (h?--h:0;s[i+h]==s[sa[rank[i]-1]+h];++h);
            height[rank[i]]=h;
        }
    }
    int fa[maxn];PII t[maxn];
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void get_ans(){
        splay.clear();
        for (int i=1;i<=n;++i){splay.insert(i,sa[i]);fa[i]=i;}
        for (int i=2;i<=n;++i) t[i-1]=make_pair(height[i],i);
        sort(t+1,t+n,greater<PII>());
        for (int i=1;i<=n-1;++i){
            int cur_height=t[i].first,cur_rank=t[i].second;
            if (!cur_height) break;
            int x=find(cur_rank),y=find(cur_rank-1);
            if (splay.size(x)>splay.size(y)) swap(x,y);
            splay.travel(x);
            for (int j=1;j<=cnt;++j){
                int a=splay.greater(y,q[j]+l);
                int b=splay.less(y,cur_height+l+q[j]+1);
                ans+=(a+b-splay.size(y));
                int c=splay.less(y,q[j]-l);
                int d=splay.greater(y,q[j]-cur_height-l-1);
                ans+=(c+d-splay.size(y));
            }
            splay.merge(y,x);fa[x]=y;
        }
    }
}SA;
void init(){
    scanf("%d%s",&l,s+1);n=strlen(s+1);
    SA.suffix_sort();SA.get_height();
}
void work(){
    SA.get_ans();
    printf("%lld\n",ans);
}
int main(){
    init();
    work();
    return 0;
}
my code

 

posted @ 2015-08-14 17:53  iamCYY  阅读(268)  评论(0编辑  收藏  举报