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

    传送门:http://www.tsinsen.com/A1484

    思路:首先对于添加操作,后缀数组是很难实现的,因为这会改变很多个后缀。

    所以换一个思路,把操作离线,倒着实现所有操作,这样插入就变成删除了。

    删除操作就好做得多了。

    先把B串接到A串后,用特殊字符隔开。

    有询问时,还是向上向下二分出一个合法区间,查询区间内有多少个可以匹配的且存在的串。

    因为要查区间和,用树状数组维护一下即可。

    记录AB串的开始结束为止,删除时移动这些指针,然后把对应的被删除的后缀从树状数组中删除,“复活”的后缀加入树状数组(因为随着B串的缩短,有的后缀又可以匹配了)即可。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int maxn=200010;
    using namespace std;
    int n,m,q[maxn],sta,eda,stb,edb,lena,t1[maxn],t2[maxn],rank[maxn],sa[maxn],sum[maxn],h[maxn],st[maxn][20],cnt,ans[maxn];
    char a[maxn<<1],b[maxn<<1],s[maxn],ch[10];
    struct bit{
    	int t[maxn];
    	void change(int x,int add){for (;x<=n;x+=x&(-x)) t[x]+=add;}
    	int query(int x){int res=0;for (;x;x-=x&(-x)) res+=t[x];return res;}
    	int query(int l,int r){return query(r)-query(l-1);};
    }T;
    
    void getsa(){
    	int *x=t1,*y=t2,p=0,m=255;
    	for (int i=1;i<=n;i++) sum[x[i]=s[i]]++;
    	for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
    	for (int i=1;i<=n;i++) sa[sum[x[i]]--]=i;
    	for (int j=1;p<n;j<<=1,m=p){
    		p=0;
    		for (int i=n-j+1;i<=n;i++) y[++p]=i;
    		for (int i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
    		memset(sum,0,sizeof(sum));
    		for (int i=1;i<=n;i++) sum[x[y[i]]]++;
    		for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
    		for (int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i];
    		swap(x,y),x[sa[1]]=p=1;
    		for (int i=2;i<=n;i++){
    			if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+j]!=y[sa[i-1]+j]) p++;
    			x[sa[i]]=p;
    		}
    	}
    	memcpy(rank,x,sizeof(rank));}
    
    void geth(){
    	for (int i=1,j=0;i<=n;i++){
    		if (rank[i]==1) continue;
    		while (s[i+j]==s[sa[rank[i]-1]+j]) j++;
    		h[rank[i]]=j;
    		if (j) j--;
    	}
    }
    
    void prework(){
    	for (int i=2;i<=n;++i) st[i][0]=h[i];
        for (int k=1;k<=19;++k)
            for (int j=1<<k;j<=n;++j)
                st[j][k]=min(st[j][k-1],st[j-(1<<(k-1))][k-1]);
    }
    
    int getmin(int l,int r){
    	if (l>=r) return n-sa[r]+1;
    	int k=log2(r-l);
    	return min(st[r][k],st[l+(1<<k)][k]);
    }
    
    int findl(int x,int len){
    	int l=1,r=x,ans;
    	while (l<=r){
    		int mid=(l+r)>>1;
    		if (getmin(mid,x)>=len) ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	return ans;
    }
    
    int findr(int x,int len){
    	int l=x,r=n,ans;
    	while (l<=r){
    		int mid=(l+r)>>1;
    		if (getmin(x,mid)>=len) ans=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return ans;
    }
    
    int query(){
    	int pos=rank[lena+stb],len=edb-stb+1;
    	return T.query(findl(pos,len),findr(pos,len));
    }
    
    void work(){
    	for (int i=1;i<=eda-edb+1;i++) T.change(rank[i],1);
    	for (int i=m;i;i--){
    		if (q[i]==1) {if (eda-sta+1>=edb-stb+1) T.change(rank[sta],-1),++sta;}
    		else if (q[i]==2) {if (eda-sta+1>=edb-stb+1) T.change(rank[eda-(edb-stb+1)+1],-1),--eda;}
    		else if (q[i]==3) {++stb;if (eda-sta+1>=edb-stb+1) T.change(rank[eda-(edb-stb+1)+1],1);}
    		else if (q[i]==4) {--edb;if (eda-sta+1>=edb-stb+1) T.change(rank[eda-(edb-stb+1)+1],1);}
    		else ans[++cnt]=query();
    	}
    	for (int i=cnt;i;i--) printf("%d
    ",ans[i]);
    }
    
    int main(){
        scanf("%s%s%d",a+maxn,b+maxn,&m);
        sta=stb=maxn;eda=maxn+strlen(a+maxn)-1;edb=maxn+strlen(b+maxn)-1;
    	for (int i=1;i<=m;i++){
    		scanf("%d",&q[i]);
    		if (q[i]==1) scanf("%s",ch),a[--sta]=ch[0];
    		else if (q[i]==2) scanf("%s",ch),a[++eda]=ch[0];
    		else if (q[i]==3) scanf("%s",ch),b[--stb]=ch[0];
    		else if (q[i]==4) scanf("%s",ch),b[++edb]=ch[0];
    		else continue;
    	}
    	for (int i=sta;i<=eda;i++) a[i-sta+1]=a[i];eda=eda-sta+1;sta=1;a[eda+1]=0;
    	for (int i=stb;i<=edb;i++) b[i-stb+1]=b[i];edb=edb-stb+1;stb=1;b[edb+1]=0;
    	for (int i=1;i<=eda;i++) s[++n]=a[i];s[++n]='$',lena=n;
    	for (int i=1;i<=edb;i++) s[++n]=b[i];s[n+1]=0;
    	getsa(),geth(),prework(),work();
    	return 0;
    }


  • 相关阅读:
    android有进度条的下载图片并且显示图片
    在Java中,直接将类的对象使用system.out.println输出
    改写toString
    Android中Uri的使用
    重写toString()
    权限管理
    实训
    第一次上传文件成功
    sql server 2005 JDBC连接遇到的问题
    JSP 权限控制
  • 原文地址:https://www.cnblogs.com/thythy/p/5493534.html
Copyright © 2011-2022 走看看