• 51Nod1553 周期串查询 字符串 哈希 线段树


    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1553.html

    题目传送门 - 51Nod1553

    题意

      有一个串只包含数字字符。串的长度为n,下标从1开始。

      有两种操作方式:

      1 l r c (1≤l≤r≤n, c是数字字符),表示将l到r这一段的字符全部改成c字符;

      2 l r d (1≤l≤r≤n, 1≤d≤r-l+1),表示询问l到r这一段区间内的子串是否是以d为周期的串。

      字符串s是以x (1≤x≤|s|),为周期的串的条件是:对于所有的 i从1到|s|-x, $s_i = s_{i + x}$ 都成立。

      $nleq 10^5$ ,操作总数 $leq 2 imes 10^5$ 。

    题解

      只要 $s[lcdots r-d] = s[l+dcdots r]$ 那么就是周期串。

      直接线段树维护哈希值就好了。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int read(){
    	int x=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;
    }
    const int N=100005;
    int n,m;
    int a[N];
    struct HashSeg{
    	int mod,P,Pow[N],sp[N];
    	int t[N<<2],sz[N<<2],add[N<<2];
    	void build(int rt,int L,int R){
    		sz[rt]=R-L+1,add[rt]=-1;
    		if (L==R){
    			t[rt]=a[L];
    			return;
    		}
    		int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
    		build(ls,L,mid);
    		build(rs,mid+1,R);
    		t[rt]=(1LL*t[ls]*Pow[sz[rs]]+t[rs])%mod;
    	}
    	void init(int _mod,int _P){
    		mod=_mod,P=_P;
    		Pow[0]=1;
    		for (int i=1;i<=n;i++)
    			Pow[i]=1LL*Pow[i-1]*P%mod;
    		sp[0]=0;
    		for (int i=1;i<=n;i++)
    			sp[i]=(sp[i-1]+Pow[i-1])%mod;
    		build(1,1,n);
    	}
    	void cover(int rt,int d){
    		t[rt]=1LL*d*sp[sz[rt]]%mod;
    		add[rt]=d;
    	}
    	void pushdown(int rt){
    		int &v=add[rt];
    		if (!~v)
    			return;
    		cover(rt<<1,v);
    		cover(rt<<1|1,v);
    		v=-1;
    	}
    	void update(int rt,int L,int R,int xL,int xR,int d){
    		if (R<xL||L>xR)
    			return;
    		if (xL<=L&&R<=xR)
    			return cover(rt,d);
    		pushdown(rt);
    		int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
    		update(ls,L,mid,xL,xR,d);
    		update(rs,mid+1,R,xL,xR,d);
    		t[rt]=(1LL*t[ls]*Pow[sz[rs]]+t[rs])%mod;
    	}
    	int query(int rt,int L,int R,int xL,int xR){
    		if (R<xL||L>xR)
    			return 0;
    		if (xL<=L&&R<=xR)
    			return 1LL*t[rt]*Pow[xR-R]%mod;
    		pushdown(rt);
    		int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
    		return (query(ls,L,mid,xL,xR)+query(rs,mid+1,R,xL,xR))%mod;
    	}
    }T0,T1;
    int main(){
    	n=read(),m=read()+read();
    	for (int i=1;i<=n;i++)
    		scanf("%1d",&a[i]);
    	T0.init(998244353,233);
    	T1.init(1e9+7,101);
    	while (m--){
    		int opt=read(),L=read(),R=read(),d=read();
    		if (opt==1){
    			T0.update(1,1,n,L,R,d);
    			T1.update(1,1,n,L,R,d);
    		}
    		else {
    			if (R-L+1<=d)
    				puts("YES");
    			else if (T0.query(1,1,n,L,R-d)==T0.query(1,1,n,L+d,R))
    				   &&T1.query(1,1,n,L,R-d)==T1.query(1,1,n,L+d,R))
    				puts("YES");
    			else
    				puts("NO");
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    取消PHPCMS V9后台新版本升级提示信息
    phpcmsv9全站搜索,不限模型
    jq瀑布流代码
    phpcms v9模版调用代码
    angular.js添加自定义服务依赖项方法
    angular多页面切换传递参数
    angular路由最基本的实例---简单易懂
    作用域事件传播
    利用angular控制元素的显示和隐藏
    利用angular给节点添加样式
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/51Nod1553.html
Copyright © 2020-2023  润新知