描述
http://www.lydsy.com/JudgeOnline/problem.php?id=3207
给出一个长度为\(n\)的串,以及\(m\)个长度为\(k\)的串,求每个长度为\(k\)的串在原串\([x,y]\)区间是否出现过.
分析
这道题要求对比长度为\(k\)的串,于是我们把这些串的Hash值都算出来,问题就转化成了求\([x,y]\)的区间中是否出现过某Hash值.
求区间中某一个值出现了多少次,可以用主席树.
p.s.
1.学习了主席树指针的写法,比数组慢好多啊...看来有必要去学一学平衡树的数组写法...不过好处是不用自己算空间...
2.这道题自己算空间的话会MLE,所以卡着空间限制就好,估计数据比较小,可以过.
数组:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=200000+5,X=27; 5 typedef unsigned long long ull; 6 const ull INF=~0ull; 7 int n,m,k,cnt; 8 int a[maxn],rt[maxn]; 9 ull s[maxn],x=1; 10 struct node{ int l,r,s; }t[maxn*50]; 11 inline int read(int &x){ x=0;int k=1;char c;for(c=getchar();c<‘0‘||c>‘9‘;c=getchar())if(c==‘-‘)k=-1;for(;c>=‘0‘&&c<=‘9‘;c=getchar())x=x*10+c-‘0‘;return x*=k; } 12 void update(ull l,ull r,int &pos,ull d){ 13 t[++cnt]=t[pos]; pos=cnt; t[pos].s++; 14 if(l==r) return; 15 ull mid=l+(r-l)/2; 16 if(d<=mid) update(l,mid,t[pos].l,d); 17 else update(mid+1,r,t[pos].r,d); 18 } 19 bool query(int x,int y,ull l,ull r,ull d){ 20 if(t[y].s-t[x].s==0) return false; 21 if(l==r) return true; 22 ull mid=l+(r-l)/2; 23 if(d<=mid) return query(t[x].l,t[y].l,l,mid,d); 24 else return query(t[x].r,t[y].r,mid+1,r,d); 25 } 26 int main(){ 27 read(n); read(m); read(k); 28 for(int i=1;i<=n;i++){ 29 read(a[i]); 30 s[i]=s[i-1]*X+(ull)a[i]; 31 } 32 for(int i=1;i<=k;i++) x*=X; 33 for(int i=k;i<=n;i++) rt[i]=rt[i-1], update(0ull,INF,rt[i],s[i]-s[i-k]*x); 34 for(int i=1;i<=m;i++){ 35 ull hash=0; bool ans; 36 int l,r; read(l); read(r); 37 for(int j=1,t;j<=k;j++) hash=hash*X+read(t); 38 if(r+1-l<k) ans=false; 39 else ans=query(rt[l+k-2],rt[r],0ull,INF,hash); 40 ans?puts("No"):puts("Yes"); 41 } 42 return 0; 43 }
指针:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=200000+5,X=27; 5 typedef unsigned long long ull; 6 const ull INF=~0ull; 7 int n,m,k,cnt; 8 int a[maxn]; 9 ull s[maxn],x=1; 10 struct node{ 11 node* l,* r; int s; 12 node(){} 13 node(node *l,node* r,int s):l(l),r(r),s(s){} 14 }* rt[maxn],* null; 15 inline int read(int &x){ x=0;int k=1;char c;for(c=getchar();c<‘0‘||c>‘9‘;c=getchar())if(c==‘-‘)k=-1;for(;c>=‘0‘&&c<=‘9‘;c=getchar())x=x*10+c-‘0‘;return x*=k; } 16 node* update(node* t,ull l,ull r,ull d){ 17 if(l==r) return new node(null,null,t->s+1); 18 ull mid=l+(r-l)/2; 19 if(d<=mid) return new node(update(t->l,l,mid,d),t->r,t->s+1); 20 else return new node(t->l,update(t->r,mid+1,r,d),t->s+1); 21 } 22 bool query(node* x,node* y,ull l,ull r,ull d){ 23 if(y->s-x->s==0) return false; 24 if(l==r) return true; 25 ull mid=l+(r-l)/2; 26 if(d<=mid) return query(x->l,y->l,l,mid,d); 27 else return query(x->r,y->r,mid+1,r,d); 28 } 29 int main(){ 30 read(n); read(m); read(k); 31 null=new node; 32 null->l=null, null->r=null, null->s=0; 33 for(int i=1;i<=n;i++){ 34 read(a[i]); 35 s[i]=s[i-1]*X+(ull)a[i]; 36 } 37 for(int i=1;i<=k;i++) x*=X; 38 rt[k-1]=new node(null,null,0); 39 for(int i=k;i<=n;i++) rt[i]=update(rt[i-1],0ull,INF,s[i]-s[i-k]*x); 40 for(int i=1;i<=m;i++){ 41 ull hash=0; bool ans; 42 int l,r; read(l); read(r); 43 for(int j=1,t;j<=k;j++) hash=hash*X+read(t); 44 if(r+1-l<k) ans=false; 45 else ans=query(rt[l+k-2],rt[r],0ull,INF,hash); 46 ans?puts("No"):puts("Yes"); 47 } 48 return 0; 49 }
时间: 2024-09-27 20:24:03