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}$ 都成立。
$n\leq 10^5$ ,操作总数 $\leq 2\times 10^5$ 。
题解
只要 $s[l\cdots r-d] = s[l+d\cdots 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; }