• Query on a string 线段树


    动态维护s1的所有区间内s2的个数

    开始的想法是线段树区间保存有多少个完整的s2串,当成区间合并做,暂时没调出来bug:

    #include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<iostream>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define pb push_back
    #define FOR(a) for(int i=1;i<=a;i++)
    const int inf=0x3f3f3f3f;
    const ll Linf=9e18;
    const int maxn=1e5+7; 
    const ll mod=100003;
    const double eps=1e-6;
    
    /******************************************************/  
    namespace fastIO{    
        #define BUF_SIZE 100000    
        #define OUT_SIZE 100000    
        #define ll long long    
        //fread->read    
        bool IOerror=0;    
        inline char nc(){    
            static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;    
            if (p1==pend){    
                p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);    
            if (pend==p1){IOerror=1;return -1;}    
            //{printf("IO error!
    ");system("pause");for (;;);exit(0);}    
        }    
        return *p1++;    
    }    
    inline bool blank(char ch){return ch==' '||ch=='
    '||ch=='
    '||ch=='	';}    
    inline void read(int &x){    
        bool sign=0; char ch=nc(); x=0;    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        if (ch=='-')sign=1,ch=nc();    
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';    
        if (sign)x=-x;    
    }    
    inline void read(ll &x){    
        bool sign=0; char ch=nc(); x=0;    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        if (ch=='-')sign=1,ch=nc();    
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';    
        if (sign)x=-x;    
    }    
    inline void read(double &x){    
        bool sign=0; char ch=nc(); x=0;    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        if (ch=='-')sign=1,ch=nc();    
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';    
        if (ch=='.'){    
            double tmp=1; ch=nc();    
            for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');    
        }    
        if (sign)x=-x;    
    }    
    inline void read(char *s){    
        char ch=nc();    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;    
        *s=0;    
    }    
    inline void read(char &c){    
        for (c=nc();blank(c);c=nc());    
        if (IOerror){c=-1;return;}    
    }   
    #undef OUT_SIZE    
    #undef BUF_SIZE    
    }; using namespace fastIO;  
    /*****************************************************/  
    
    
    int n;int len,len2;
    char s1[maxn],s2[maxn];
    
    struct NODE{
    	int l,r;
    	int val;
    }ST[maxn<<2];
    
    void pushup(int rt){
    	ST[rt].val=ST[rt<<1].val+ST[rt<<1|1].val;
    	int flag=0;
    	for(int l=len2-1;l>=1;l--){
    
    		if(ST[rt<<1].r-ST[rt<<1].l+1<l
    		||ST[rt<<1|1].r-ST[rt<<1|1].l+1<len2-l	
    		)continue;
    
    		int pos=1;	
    		int ok=1;		//这个分配是否可行
    		int r=len2-l;	//左区间l个右区间r个
    		for(int i= ST[rt<<1].r-l+1 ;i<=ST[rt<<1].r;i++){
    			if(s1[i]==s2[pos]){
    				pos++;
    			}else{
    				ok=0;break;
    			}
    		}
    		if(ok==0)continue;
    		for(int i=ST[rt<<1|1].l;i<=ST[rt<<1|1].l + r-1;i++){
    			if(s1[i]==s2[pos]){
    				pos++;
    				if(pos>len2){
    					break;
    				}
    			}else{
    				ok=0;break;
    			}
    		}
    		if(ok){flag++;}
    	}
    	if(flag)ST[rt].val+=flag;
    }
    void build(int l,int r,int rt){
    	ST[rt].l=l;ST[rt].r=r;ST[rt].val=0;
    	if(l==r){return;}
    	int m=l+r>>1;
    	build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt);
    }
    void update(int a,char b,int l,int r,int rt){
    	if(l==r){s1[a]=b;return;}
    	int m=l+r>>1;
    	if(a<=m)update(a,b,l,m,rt<<1);
    	else update(a,b,m+1,r,rt<<1|1);
    	pushup(rt);
    }
    
    int query(int a,int b,int l,int r,int rt){
    	if(r<a || l>b)return 0;
    	if(a<=l && b>=r){
    		return ST[rt].val;
    	}
    	int m=l+r>>1;
    	int ret=0;
    	if(a<=m)ret+=query(a,b,l,m,rt<<1);
    	if(b>m)ret+=query(a,b,m+1,r,rt<<1|1);
    
    	int flag=0;
    	if(a<=m && b>m && b-a+1>=len2){
    		int pos=1;
    		for(int l1=len2-1;l1>=1;l1--){
    			int r1=len2-l1;	//左区间l1个右区间r1个
    			if(ST[rt<<1].r-ST[rt<<1].l+1<l1
    			||ST[rt<<1|1].r-ST[rt<<1|1].l+1<r1
    			)continue;
    
    			int ok=1;
    			for(int i=ST[rt<<1].r-l1+1;i<=ST[rt<<1].r;i++){
    				if(s1[i]==s2[pos]){
    					pos++;
    				}else{
    					ok=0;break;
    				}
    			}
    			if(!ok)continue;
    			for(int i=ST[rt<<1|1].l;i<=ST[rt<<1|1].l+r1-1;i++){
    				if(s1[i]==s2[pos]){
    					pos++;
    					if(pos>len2){break;}
    				}else{
    					ok=0;break;
    				}
    			}
    			if(ok){
    				flag++;
    			}
    		}	
    	}
    	if(flag)ret+=flag;
    	return ret;	
    }
    
    char op[2];
    int main(){
    	int T;read(T);
    	//scanf("%d",&T);
    	while(T--){
    		//scanf("%d",&n);
    		read(n);
    		//scanf("%s%s",s1+1,s2+1);
    		read(s1+1);read(s2+1);
    		len=strlen(s1+1);
    		len2=strlen(s2+1);
    		build(1,len,1);
    
    		for(int i=1;i<=n;i++){
    			//scanf("%s",op);
    			read(op);
    			if(op[0]=='Q'){
    				int x,y;
    				//scanf("%d%d",&x,&y);
    				read(x);read(y);
    				if(y-x+1<len2){
    					printf("0
    ");continue;
    				}
    				printf("%d
    ",query(x,y,1,len,1));
    			}else{
    				int x;char ch[2];
    				//scanf("%d%s",&x,ch);
    				read(x);read(ch);
    				if(ch[0]==s1[x])continue;
    				update(x,ch[0],1,len,1);
    			}
    		}
    		puts("");
    	}
    }
    一个简单的做法是单点0,1表示作为头是否可以匹配,这个好写多了

    #include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<iostream>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define pb push_back
    #define FOR(a) for(int i=1;i<=a;i++)
    const int inf=0x3f3f3f3f;
    const ll Linf=9e18;
    const int maxn=1e5+7; 
    const ll mod=100003;
    const double eps=1e-6;
    
    /******************************************************/  
    namespace fastIO{    
        #define BUF_SIZE 100000    
        #define OUT_SIZE 100000    
        #define ll long long    
        //fread->read    
        bool IOerror=0;    
        inline char nc(){    
            static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;    
            if (p1==pend){    
                p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);    
            if (pend==p1){IOerror=1;return -1;}    
            //{printf("IO error!
    ");system("pause");for (;;);exit(0);}    
        }    
        return *p1++;    
    }    
    inline bool blank(char ch){return ch==' '||ch=='
    '||ch=='
    '||ch=='	';}    
    inline void read(int &x){    
        bool sign=0; char ch=nc(); x=0;    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        if (ch=='-')sign=1,ch=nc();    
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';    
        if (sign)x=-x;    
    }    
    inline void read(ll &x){    
        bool sign=0; char ch=nc(); x=0;    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        if (ch=='-')sign=1,ch=nc();    
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';    
        if (sign)x=-x;    
    }    
    inline void read(double &x){    
        bool sign=0; char ch=nc(); x=0;    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        if (ch=='-')sign=1,ch=nc();    
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';    
        if (ch=='.'){    
            double tmp=1; ch=nc();    
            for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');    
        }    
        if (sign)x=-x;    
    }    
    inline void read(char *s){    
        char ch=nc();    
        for (;blank(ch);ch=nc());    
        if (IOerror)return;    
        for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;    
        *s=0;    
    }    
    inline void read(char &c){    
        for (c=nc();blank(c);c=nc());    
        if (IOerror){c=-1;return;}    
    }   
    #undef OUT_SIZE    
    #undef BUF_SIZE    
    }; using namespace fastIO;  
    /*****************************************************/  
    int len1,len2;
    char s1[maxn],s2[maxn];
    char op[2],ch[2];
    int x,y;
    int arr[maxn];
    
    int same;
    
    struct NODE{
    	int val;
    }ST[maxn<<2];	//区间内有多少个头(
    
    void pushup(int rt){ST[rt].val=ST[rt<<1].val+ST[rt<<1|1].val;}
    void build(int l,int r,int rt){
    	if(l==r){
    		ST[rt].val=arr[l];return;
    	}
    	int m=l+r>>1;
    	build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt);
    }
    void update(int a,int b,int l,int r,int rt){	//区间[a,b]影响
    	if(l>b || r<a)return;
    	if(l+len2-1>len1)return;
    	if(l==r){	//计算s1[l]作为头是1还是0
    
    		int flag=1;
    		for(int i=l;i<=l+len2-1;i++){
    			//if(i>len1){flag=0;break;}
    			if(s1[i]!=s2[i-l+1]){
    				flag=0;break;
    			}
    		}
    		if(flag)ST[rt].val=1;else ST[rt].val=0;
    		return;
    	}
    	int m=l+r>>1;
    	update(a,b,l,m,rt<<1);update(a,b,m+1,r,rt<<1|1);
    	pushup(rt);
    }
    int query(int a,int b,int l,int r,int rt){
    	if(a<=l&&b>=r)return ST[rt].val;
    	int m=l+r>>1,ret=0;
    	if(a<=m)ret=query(a,b,l,m,rt<<1);
    	if(b>m)ret+=query(a,b,m+1,r,rt<<1|1);
    	return ret;
    }
    
    int main(){
    	int T;
    	read(T);
    	//scanf("%d",&T);
    	while(T--){
    		int n;
    		//scanf("%d",&n);scanf("%s%s",s1+1,s2+1);
    		read(n);
    		read(s1+1);read(s2+1);
    		len1=strlen(s1+1);len2=strlen(s2+1);
    
    		for(int i=1;i<=len1-len2+1;i++){
    			int flag=1;
    			for(int j=i;j<=i+len2-1;j++){
    				if(s1[j]!=s2[j-i+1]){
    					flag=0;break;
    				}
    			}
    			if(flag)arr[i]=1;else arr[i]=0;
    		}
    		build(1,len1,1);
    
    		while(n--){
    			read(op);
    			//scanf("%s",op);
    			if(op[0]=='Q'){
    				read(x);read(y);
    				//scanf("%d%d",&x,&y);
    				if(y-x+1<len2){
    					printf("0
    ");continue;
    				}
    				printf("%d
    ",query(x,y-len2+1,1,len1,1));
    			}else{
    				read(x);read(ch);
    				//scanf("%d%s",&x,ch);
    				if(ch[0]!=s1[x])same=0;
    				else same=1;
    				if(same)continue;
    				s1[x]=ch[0];
    				update(max(1,x-len2+1),x,1,len1,1);
    			}
    		}
    		puts("");
    	}
    }





  • 相关阅读:
    【Python3网络爬虫开发实战】 1-开发环境配置
    Elasticsearch 基本介绍及其与 Python 的对接实现
    深度学习 GPU环境 Ubuntu 16.04 + Nvidia GTX 1080 + Python 3.6 + CUDA 9.
    React组件方法中为什么要绑定this
    中级前端开发推荐书籍
    20万行代码,搞得定不?
    华为云数据库TaurusDB性能挑战赛,50万奖金等你来拿!
    00036_private
    使用spring等框架的web程序在Tomcat下的启动顺序及思路理清
    http304状态码缓存设置问题
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611257.html
Copyright © 2020-2023  润新知