zoukankan      html  css  js  c++  java
  • tsinsenA1484. two strings(罗干)

    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
    ",ans[i]);
    }
    int main(){
        init();
        work();
        return 0;
    }
    my code
  • 相关阅读:
    windows下mysql初始密码设置
    python生成简单的验证码
    python中HTMLParser简单理解
    Windows批处理(cmd/bat)常用命令小结
    文件结束的判断和结束符的理解
    交换机与路由器
    结构体字节对齐
    有(无)符号char型及其溢出问题
    kubernetes离线包安装教程
    kubernetes(K8S)快速安装与配置集群搭建图文教程
  • 原文地址:https://www.cnblogs.com/iamCYY/p/4730802.html
Copyright © 2011-2022 走看看