码迷,mamicode.com
首页 > 其他好文 > 详细

[loj2572]字符串

时间:2021-05-24 16:53:45      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:data   sed   bsp   style   大小   abc   第一个   space   merge   

约定:以下字符串下标从1开始,令$n=|s|$

对于字符串$s_{1}$和$s_{2}$,定义以下信息——

定义$s_{1}\approx s_{2}$当且仅当$s_{1}[1,l]=s_{2}[1,l]$(其中$l=\min(|s_{1}|,|s_{2}|)$)

定义$s_{1}\ll s_{2}$当且仅当$s_{1}<s_{2}$且$s_{1}\not\approx s_{2}$,$s_{1}\gg s_{2}$当且仅当$s_{1}>s_{2}$且$s_{1}\not\approx s_{2}$

 

定义$f(s)$为$s$中最小后缀的位置,即$s[f(s),n]=\min_{i=1}^{n}s[i,n]$

结论:若$s=caab$,则$f(s)\ne |c|+|a|+1$(其中$a,b,c$为任意字符串,且$a,b$非空)

考虑取另外$|c|+1$和$|c|+2|a|+1$的位置,即求证$aab<ab$或$b<ab$

当$ab<b$时,前者显然成立,否则由于$b\ne ab$,后者即成

 

$\forall x\in [1,n]$,$x\in S$当且仅当其满足:

1.$\forall 1\le y\le n,s[x,n]\not\ll s[y,n]$

2.$\forall 1\le y<x且2x-y\le n,s[y,n]\not\approx s[x,n]$

(这个条件即等价于不存在$s[1,n]=caab$使得$f(s)=|c|+|a|+1$)

显然,有$f(s)\in S$,下面考虑$|S|$的大小——

结论:$|S|\sim o(\log n)$

若$x,y\in S$(不妨假设$x<y$),根据第一个性质,则有$s[x,n]\approx s[y,n]$

若$2y-x\le n$,即可以得到$s[x,y)=s[y,2y-x)$,与第2个性质矛盾

因此$2y-x>n$,也即$2|s[y,n]|\le |s[x,n]|$,因此将$S$中的$x$写作$n-x+1$从小到大排列后,后一项大于等于前一项的两倍且值域为$[1,n]$,即有$|S|\sim o(\log n)$

当求出$s[l,r]$对应的$S$后,$S$中的最大值即为答案,求最大值复杂度为$o(\log n)$

 

下面,考虑两个字符串$s_{1}$和$s_{2}$,两者的$S$分别为$S_{1}S_{2}$,下面来求$s=s_{1}s_{2}$的$S$

先将$S_{2}$中所有元素加上$|s_{1}|$,注意到$S\subseteq S_{1}\cup S_{2}$,从小到大枚举$x\in S_{1}\cup S_{2}$中的元素$x$,并判定能否加入$S_{i}$中,判定只需要考虑$S$中的元素,具体即——

初始$S$为空,若$S$为空则直接加入,否则令$y$为当前$S_{i}$中的最大值,考虑$s[x,n]$和$s[y,n]$的关系:

1.$s[x,n]\approx s[y,n]$,若$2x-y>n$则加入$x$

2.$s[x,n]\gg s[y,n]$,不加入$x$

3.$s[x,n]\ll s[y,n]$,令$S_{i}=\{x\}$

比较可以使用二分+哈希,复杂度为$o(\log n)$,哈希用分块维护可以做到修改$o(\sqrt{n})$

综上,合并复杂度为$o(\log^{2}n)$,即可用线段树维护,初始复杂度为$o(n\log^{2}n)$,单次修改和查询复杂度总复杂度为$o(\log^{3}n)$,最终总复杂度为$o(n\log^{2}n+m\log^{3}n+m\sqrt{n})$,可以通过

技术图片
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 200005
  4 #define K 500
  5 #define base 500000003
  6 #define mod 998244353
  7 #define L (k<<1)
  8 #define R (L+1)
  9 #define mid (l+r>>1)
 10 struct Data{
 11     int l,r;
 12     vector<int>v;
 13 }f[N<<2];
 14 int n,m,p,x,y,z,inv,Inv,mi[N],inv_mi[N],a[N],bl[N],st[K],ed[K],tag1[K],tag2[K],sum[N];
 15 int qpow(int n,int m){
 16     int s=n,ans=1;
 17     while (m){
 18         if (m&1)ans=1LL*ans*s%mod;
 19         s=1LL*s*s%mod;
 20         m>>=1;
 21     }
 22     return ans;
 23 }
 24 int get_sum(int x,int y){
 25     return 1LL*(inv_mi[x]+mod-inv_mi[y+1])*Inv%mod;
 26 }
 27 int get_hash(int k){
 28     return (sum[k]+1LL*tag1[bl[k]]*mi[k]+1LL*tag2[bl[k]]*get_sum(st[bl[k]],k)%mod*mi[k])%mod;
 29 }
 30 void update_hash(int x,int y,int z){
 31     if (bl[x]==bl[y]){
 32         for(int i=x;i<=y;i++)sum[i]=(sum[i]+1LL*z*get_sum(x,i)%mod*mi[i])%mod;
 33         int s=1LL*z*get_sum(x,y)%mod;
 34         for(int i=y+1;i<=ed[bl[y]];i++)sum[i]=(sum[i]+1LL*s*mi[i]%mod)%mod;
 35         for(int i=bl[y]+1;i<=bl[n];i++)tag1[i]=(tag1[i]+s)%mod;
 36     }
 37     else{
 38         for(int i=x;i<=ed[bl[x]];i++)sum[i]=(sum[i]+1LL*z*get_sum(x,i)%mod*mi[i])%mod;
 39         int s=1LL*z*get_sum(x,ed[bl[x]])%mod;
 40         for(int i=bl[x]+1;i<bl[y];i++){
 41             tag1[i]=(tag1[i]+s)%mod;
 42             tag2[i]=(tag2[i]+z)%mod;
 43             s=(s+1LL*z*get_sum(st[i],ed[i]))%mod;
 44         }
 45         for(int i=st[bl[y]];i<=y;i++)sum[i]=(sum[i]+(1LL*z*get_sum(st[bl[y]],i)+s)%mod*mi[i])%mod;
 46         s=(s+1LL*z*get_sum(st[bl[y]],y))%mod;
 47         for(int i=y+1;i<=ed[bl[y]];i++)sum[i]=(sum[i]+1LL*s*mi[i]%mod)%mod;
 48         for(int i=bl[y]+1;i<=bl[n];i++)tag1[i]=(tag1[i]+s)%mod;
 49     }
 50 }
 51 int query_hash(int x,int y){
 52     return (get_hash(y)-1LL*mi[y-x+1]*get_hash(x-1)%mod+mod)%mod;
 53 }
 54 int lcp(int x,int y,int i){
 55     int l=0,r=i-y+1;
 56     while (l<r){
 57         int midd=(l+r+1>>1);
 58         if (query_hash(x,x+midd-1)==query_hash(y,y+midd-1))l=midd;
 59         else r=midd-1;
 60     }
 61     return l;
 62 }
 63 int cmp(int x,int y,int i){
 64     int l=lcp(x,y,i);
 65     if (l==i-y+1)return 0;
 66     if (query_hash(x+l,x+l)<query_hash(y+l,y+l))return -1;
 67     return 1;
 68 }
 69 Data merge(Data a,Data b){
 70     if (!a.l)return b;
 71     if (!b.l)return a;
 72     Data ans;
 73     ans.l=a.l,ans.r=b.r;
 74     ans.v.clear();
 75     for(int i=0;i<a.v.size();i++){
 76         if (!ans.v.size())ans.v.push_back(a.v[i]);
 77         else{
 78             int x=ans.v.back(),y=a.v[i],p=cmp(x,y,b.r);
 79             if (p>0)ans.v.clear();
 80             if ((p>0)||(!p)&&(2*y-x>b.r))ans.v.push_back(y);
 81         }
 82     }
 83     for(int i=0;i<b.v.size();i++){
 84         if (!ans.v.size())ans.v.push_back(b.v[i]);
 85         else{
 86             int x=ans.v.back(),y=b.v[i],p=cmp(x,y,b.r);
 87             if (p>0)ans.v.clear();
 88             if ((p>0)||(!p)&&(2*y-x>b.r))ans.v.push_back(y);
 89         }
 90     }
 91     return ans;
 92 }
 93 void build(int k,int l,int r){
 94     if (l==r){
 95         f[k].l=f[k].r=l;
 96         f[k].v.push_back(l);
 97         return;
 98     }  
 99     build(L,l,mid);
100     build(R,mid+1,r);
101     f[k]=merge(f[L],f[R]);
102 }
103 void update(int k,int l,int r,int x,int y){
104     if ((l>y)||(x>r))return;
105     if ((x<=l)&&(r<=y))return;
106     update(L,l,mid,x,y);
107     update(R,mid+1,r,x,y);
108     f[k]=merge(f[L],f[R]);
109 }
110 Data query(int k,int l,int r,int x,int y){
111     if ((l>y)||(x>r))return f[0];
112     if ((x<=l)&&(r<=y))return f[k];
113     return merge(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
114 }
115 int main(){
116     inv=qpow(base,mod-2),Inv=qpow(mod+1-inv,mod-2);
117     mi[0]=inv_mi[0]=1;
118     for(int i=1;i<N;i++)mi[i]=1LL*mi[i-1]*base%mod;
119     for(int i=1;i<N;i++)inv_mi[i]=1LL*inv_mi[i-1]*inv%mod;
120     scanf("%d%d",&n,&m);
121     for(int i=1;i<=n;i++){
122         bl[i]=i/K+1;
123         if (!st[bl[i]])st[bl[i]]=i;
124         ed[bl[i]]=i;
125     }
126     for(int i=1;i<=n;i++){
127         scanf("%d",&a[i]);
128         a[i]+=base/2;
129         sum[i]=(1LL*sum[i-1]*base+a[i])%mod;
130     }
131     build(1,1,n);
132     for(int i=1;i<=m;i++){
133         scanf("%d%d%d",&p,&x,&y);
134         if (p==1){
135             scanf("%d",&z);
136             update_hash(x,y,(z+mod)%mod);
137             update(1,1,n,x,y);
138         }
139         if (p==2)printf("%d\n",query(1,1,n,x,y).v.back());
140     }
141 } 
View Code

 

[loj2572]字符串

标签:data   sed   bsp   style   大小   abc   第一个   space   merge   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/14787603.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!