码迷,mamicode.com
首页 > 其他好文 > 详细

tsinsenA1484. two strings(罗干)

时间:2015-08-14 18:49:29      阅读:100      评论:0      收藏:0      [点我收藏+]

标签:

http://www.tsinsen.com/A1484

  在线插入并不好做,我们将所有操作离线,变为删除操作。

  每次询问的时候对于当前B串所在起始位置及其长度向上向下二分,然后查询区间内合法的当前A串内的匹配点即可。用树状数组维护。

技术分享
#include<bits/stdc++.h>
using namespace std;
const int maxlen=200015,maxm=200015,maxk=20;
int tmp,sta,eda,stb,edb,len,m,w[maxm];
char a[maxlen*2],b[maxlen*2],s[maxlen];
struct Tbit{
    int T[maxlen];
    void modify(int x,int v){for (int p=x;p<=len;p+=p&-p) T[p]+=v;}
    int query(int l,int r){
        int res=0;
        for (int p=l-1;p>=1;p-=p&-p) res-=T[p];
        for (int p=r;p>=1;p-=p&-p) res+=T[p];
        return res;
    }
}bit;
struct Tsuffix_array{
    int sum[maxlen],sa[maxlen],rank[maxlen],tsa[maxlen],trank[maxlen];
    bool cmp(int i,int j,int l){
        if (i+l>len||j+l>len) 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<=len;++i) ++sum[rank[i]=s[i]];
        for (i=1;i<=m;++i) sum[i]+=sum[i-1];
        for (i=len;i>=1;--i) sa[sum[rank[i]]--]=i;
        for (p=0,j=1;p<len;j<<=1,m=p){
            for (p=0,i=len-j+1;i<=len;++i) tsa[++p]=i;
            for (i=1;i<=len;++i) if (sa[i]>j) tsa[++p]=sa[i]-j;
            for (i=0;i<=m;++i) sum[i]=0;
            for (i=1;i<=len;++i) ++sum[rank[tsa[i]]];
            for (i=1;i<=m;++i) sum[i]+=sum[i-1];
            for (i=len;i>=1;--i) sa[sum[rank[tsa[i]]]--]=tsa[i];
            for (p=trank[sa[1]]=1,i=2;i<=len;++i) trank[sa[i]]=cmp(sa[i],sa[i-1],j)?p:++p;
            memcpy(rank,trank,sizeof(int)*(len+1));
        }
    }
    int height[maxlen];
    void get_height(){
        for (int h=0,i=1;i<=len;++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 fmn[maxk][maxlen];
    void prepare(){
        for (int i=2;i<=len;++i) fmn[0][i]=height[i];
        for (int k=1;k<maxk;++k)
            for (int j=1<<k;j<=len;++j)
                fmn[k][j]=min(fmn[k-1][j],fmn[k-1][j-(1<<(k-1))]);
    }
    int LCP(int x,int y){
        if (++x>y) return len-sa[y]+1;
        int k=log2(y-x+1);
        return min(fmn[k][y],fmn[k][x+(1<<k)-1]);
    }
    int calc_up(int pos,int lim){
        int l=1,r=pos,res;
        while (l<=r){
            int mid=(l+r)>>1;
            LCP(mid,pos)>=lim?r=(res=mid)-1:l=mid+1;
        }
        return res;
    }
    int calc_low(int pos,int lim){
        int l=pos,r=len,res;
        while (l<=r){
            int mid=(l+r)>>1;
            LCP(pos,mid)>=lim?l=(res=mid)+1:r=mid-1;
        }
        return res;
    }
    int query(){
        int pos=rank[tmp+stb],lim=edb-stb+1;
        return bit.query(calc_up(pos,lim),calc_low(pos,lim));
    }
}SA;
void init(){
    sta=stb=maxlen;scanf("%s%s%d",a+maxlen,b+maxlen,&m);
    eda=maxlen+strlen(a+maxlen)-1;edb=maxlen+strlen(b+maxlen)-1;
    for (int i=1;i<=m;++i){
        char c[2];scanf("%d",&w[i]);
        switch (w[i]){
            case 1:scanf("%s",c);a[--sta]=c[0];break;
            case 2:scanf("%s",c);a[++eda]=c[0];break;
            case 3:scanf("%s",c);b[--stb]=c[0];break;
            case 4:scanf("%s",c);b[++edb]=c[0];break;
            default:break;
        }
    }
    for (int i=sta;i<=eda;++i) a[i-sta+1]=a[i];a[eda-sta+2]=0;eda=eda-sta+1;sta=1;
    for (int i=stb;i<=edb;++i) b[i-stb+1]=b[i];b[edb-stb+2]=0;edb=edb-stb+1;stb=1;
    for (int i=1;i<=eda;++i) s[++len]=a[i];s[++len]=#;tmp=len;
    for (int i=1;i<=edb;++i) s[++len]=b[i];s[len+1]=0;
}
vector<int> ans;
void work(){
    SA.suffix_sort();SA.get_height();SA.prepare();
    for (int i=1;i<=eda-edb+1;++i) bit.modify(SA.rank[i],1);
    for (int tim=m;tim>=1;--tim)
        switch (w[tim]){
            case 1:if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[sta],-1);++sta;break;
            case 2:if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[eda-(edb-stb+1)+1],-1);--eda;break;
            case 3:++stb;if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[eda-(edb-stb+1)+1],1);break;
            case 4:--edb;if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[eda-(edb-stb+1)+1],1);break;
            case 5:ans.push_back(SA.query());break;
        }
    for (int i=ans.size()-1;i>=0;--i) printf("%d\n",ans[i]);
}
int main(){
    init();
    work();
    return 0;
}
my code

 

tsinsenA1484. two strings(罗干)

标签:

原文地址:http://www.cnblogs.com/iamCYY/p/4730802.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!