字符串[未AC](后缀自动机):HEOI 2016 str
超级恶心,先后用set维护right,再用主席树维护,全部超时,本地测是AC的。放心,BZOJ上还是1S限制,貌似只有常数优化到一定境界的人才能AC吧。
总之我是精神胜利了哦耶QAQ
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #define lb lower_bound 5 #define ub upper_bound 6 #include <set> 7 using namespace std; 8 const int N=200010; 9 int fa[N][20],ch[N][2],len[N],pos[N]; 10 int lst,cnt;set<int>t[N]; 11 int n,Q,a,b,c,d;char s[N]; 12 void Init(){lst=cnt=1;} 13 void Insert(int c){ 14 int p=lst,np=lst=++cnt;len[np]=len[p]+1; 15 while(p&&ch[p][c]==0)ch[p][c]=np,p=fa[p][0]; 16 if(!p)fa[np][0]=1; 17 else{ 18 int q=ch[p][c],nq; 19 if(len[q]==len[p]+1)fa[np][0]=q; 20 else{ 21 len[nq=++cnt]=len[p]+1; 22 fa[nq][0]=fa[q][0];fa[q][0]=fa[np][0]=nq; 23 memcpy(ch[nq],ch[q],sizeof(ch[q])); 24 while(ch[p][c]==q)ch[p][c]=nq,p=fa[p][0]; 25 } 26 } 27 } 28 int cntE,fir[N],to[N],nxt[N]; 29 void addedge(int a,int b){ 30 nxt[++cntE]=fir[a]; 31 to[fir[a]=cntE]=b; 32 } 33 34 set<int>Merge(set<int>x,set<int>y){ 35 if(x.size()<y.size())swap(x,y); 36 x.insert(y.begin(),y.end()); 37 //delete &y; 38 return x; 39 } 40 41 void DFS(int x){ 42 for(int i=fir[x];i;i=nxt[i]) 43 DFS(to[i]),t[x]=Merge(t[x],t[to[i]]); 44 } 45 46 bool Judge(int p,int l,int r){ 47 return t[p].lb(l)!=t[p].ub(r); 48 } 49 50 int Find(int x,int l){ 51 for(int i=17;i>=0;i--) 52 if(fa[x][i]&&len[fa[x][i]]>=l) 53 x=fa[x][i]; 54 return x; 55 } 56 57 int Solve(){ 58 int l=0,r=min(d-c,b-a)+1; 59 while(l<=r){ 60 int mid=(l+r)>>1; 61 int p=Find(pos[c],mid); 62 if(Judge(p,a,b-mid+1))l=mid+1; 63 else r=mid-1; 64 } 65 return r; 66 } 67 68 69 int main(){ 70 freopen("heoi2016_str5.in","r",stdin); 71 freopen("heoi2016_str.out","w",stdout); 72 Init();scanf("%d%d%s",&n,&Q,s+1); 73 for(int i=n;i>=1;i--){Insert(s[i]-'a');t[pos[i]=lst].insert(i);} 74 for(int i=2;i<=cnt;i++)addedge(fa[i][0],i);DFS(1); 75 for(int k=1;k<=17;k++) 76 for(int i=1;i<=cnt;i++) 77 fa[i][k]=fa[fa[i][k-1]][k-1]; 78 while(Q --){ 79 scanf("%d%d%d%d",&a,&b,&c,&d); 80 printf("%d\n",Solve()); 81 } 82 return 0; 83 }
然后是应该AC的:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <ctime> 5 using namespace std; 6 const int N=200010; 7 int fa[N][20],ch[N][26],len[N],pos[N]; 8 int lst,cnt,n,Q;char s[N]; 9 void Init(){lst=cnt=1;} 10 void Insert(int c){ 11 int p=lst,np=lst=++cnt;len[np]=len[p]+1; 12 while(p&&ch[p][c]==0)ch[p][c]=np,p=fa[p][0]; 13 if(!p)fa[np][0]=1; 14 else{ 15 int q=ch[p][c],nq; 16 if(len[q]==len[p]+1)fa[np][0]=q; 17 else{ 18 len[nq=++cnt]=len[p]+1; 19 fa[nq][0]=fa[q][0];fa[q][0]=fa[np][0]=nq; 20 memcpy(ch[nq],ch[q],sizeof(ch[q])); 21 while(ch[p][c]==q)ch[p][c]=nq,p=fa[p][0]; 22 } 23 } 24 } 25 int cntE,fir[N],to[N],nxt[N]; 26 void addedge(int a,int b){ 27 nxt[++cntE]=fir[a]; 28 to[fir[a]=cntE]=b; 29 } 30 31 int id[N],ed[N],tot; 32 int rt[N],sum[N*25],son[N*25][2]; 33 void Insert(int pre,int &rt,int l,int r,int g){ 34 sum[rt=++tot]=sum[pre]+1; 35 son[rt][0]=son[pre][0]; 36 son[rt][1]=son[pre][1]; 37 if(l==r)return;int mid=l+r>>1; 38 if(mid>=g)Insert(son[pre][0],son[rt][0],l,mid,g); 39 else Insert(son[pre][1],son[rt][1],mid+1,r,g); 40 } 41 int Query(int x,int l,int r,int a,int b){ 42 if(l>=a&&r<=b||!sum[x])return sum[x]; 43 int ret=0,mid=l+r>>1; 44 if(mid>=a)ret=Query(son[x][0],l,mid,a,b); 45 if(mid<b)ret+=Query(son[x][1],mid+1,r,a,b); 46 return ret; 47 } 48 49 bool Judge(int p,int l,int r){ 50 int A=Query(rt[l-1],1,cnt,id[p],ed[p]); 51 int B=Query(rt[r],1,cnt,id[p],ed[p]); 52 return A<B; 53 } 54 55 int st[N],top; 56 int main(){ 57 freopen("heoi2016_str.in","r",stdin); 58 freopen("heoi2016_str.out","w",stdout); 59 Init();scanf("%d%d%s",&n,&Q,s+1); 60 for(int i=n;i>=1;i--)Insert(s[i]-'a'),pos[i]=lst; 61 for(int i=2;i<=cnt;i++)addedge(fa[i][0],i); 62 for(int k=1;k<=18;k++)for(int i=1;i<=cnt;i++) 63 fa[i][k]=fa[fa[i][k-1]][k-1]; 64 st[top=1]=1; 65 while(top){ 66 int x=st[top]; 67 if(id[x]){ed[x]=tot;top--;} 68 else{ 69 id[x]=++tot; 70 for(int i=fir[x];i;i=nxt[i]) 71 st[++top]=to[i]; 72 } 73 } 74 75 tot=0; 76 for(int i=1;i<=n;i++) 77 Insert(rt[i-1],rt[i],1,cnt,id[pos[i]]); 78 int a,b,c,d; 79 while(Q --){ 80 scanf("%d%d%d%d",&a,&b,&c,&d); 81 int l=0,r=min(d-c,b-a)+1; 82 while(l<=r){ 83 int mid=l+r>>1,p=pos[c]; 84 for(int i=18;i>=0;i--) 85 if(fa[p][i]&&len[fa[p][i]]>=mid) 86 p=fa[p][i]; 87 if(Judge(p,a,b-mid+1))l=mid+1; 88 else r=mid-1; 89 } 90 printf("%d\n",r); 91 } 92 //printf("%lf\n", (double)clock()/CLOCKS_PER_SEC); 93 return 0; 94 }
有毒啊,后缀数组都写挂了,TLE。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N=100010; 6 int n,Q,r[N],Wa[N],Wb[N],Wv[N],Ws[N]; 7 int rk[N],sa[N],lcp[N],mm[N],Min[N][20]; 8 int len,cnt,ch[N*20][2],sum[N*20],rt[N]; 9 char s[N]; 10 bool cmp(int *p,int i,int j,int l){ 11 return p[i]==p[j]&&p[i+l]==p[j+l]; 12 } 13 14 void DA(int n,int m){ 15 int i,j,p,*x=Wa,*y=Wb; 16 for(i=0;i<m;i++)Ws[i]=0; 17 for(i=0;i<n;i++)++Ws[x[i]=r[i]]; 18 for(i=1;i<m;i++)Ws[i]+=Ws[i-1]; 19 for(i=n-1;i>=0;i--)sa[--Ws[x[i]]]=i; 20 21 for(p=1,j=1;p<n;m=p,j<<=1){ 22 for(p=0,i=n-j;i<n;i++)y[p++]=i; 23 for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; 24 for(i=0;i<m;i++)Ws[i]=0; 25 for(i=0;i<n;i++)++Ws[Wv[i]=x[y[i]]]; 26 for(i=1;i<m;i++)Ws[i]+=Ws[i-1]; 27 for(i=n-1;i>=0;i--)sa[--Ws[Wv[i]]]=y[i]; 28 for(swap(x,y),x[sa[0]]=0,i=1,p=1;i<n;i++) 29 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 30 } 31 } 32 33 void LCP(int n){ 34 int i,j,k=0; 35 for(i=1;i<=n;i++)rk[sa[i]]=i; 36 for(i=0;i<n;lcp[rk[i++]]=k) 37 for(k-=k>0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++); 38 } 39 40 #define mid ((l+r)>>1) 41 void Insert(int pre,int &rt,int l,int r,int g,int d){ 42 sum[rt=++cnt]=sum[pre]+d;ch[rt][0]=ch[pre][0]; 43 ch[rt][1]=ch[pre][1];if(l==r)return; 44 if(mid>=g)Insert(ch[pre][0],ch[rt][0],l,mid,g,d); 45 else Insert(ch[pre][1],ch[rt][1],mid+1,r,g,d); 46 } 47 48 int Query(int pre,int rt,int l,int r,int a,int b){ 49 if(l>=a&&r<=b)return sum[rt]-sum[pre];int ret=0; 50 if(mid>=a)ret=Query(ch[pre][0],ch[rt][0],l,mid,a,b); 51 if(mid<b)ret+=Query(ch[pre][1],ch[rt][1],mid+1,r,a,b); 52 return ret; 53 } 54 55 void Prepare(int n){ 56 mm[0]=-1; 57 for(int i=1;i<=n;i++){ 58 mm[i]=mm[i-1]; 59 if(!(i&i-1))mm[i]+=1; 60 Min[i][0]=lcp[i]; 61 } 62 for(int k=1;k<=mm[n];k++) 63 for(int i=1;i+(1<<k-1)<=n;i++) 64 Min[i][k]=min(Min[i][k-1],Min[i+(1<<k-1)][k-1]); 65 } 66 67 int Qmin(int x,int y){ 68 if(x>y)swap(x,y);x+=1;int l=mm[y-x+1]; 69 return min(Min[x][l],Min[y-(1<<l)+1][l]); 70 } 71 72 int a,b,c,d,lo,hi; 73 bool Check(int x,int n){ 74 int l=1,r=rk[c-1]-1,pl,pr; 75 while(l<=r){ 76 if(Qmin(mid,rk[c-1])>=x)r=mid-1; 77 else l=mid+1; 78 }pl=l; 79 l=rk[c-1]+1,r=n; 80 while(l<=r){ 81 if(Qmin(rk[c-1],mid)>=x)l=mid+1; 82 else r=mid-1; 83 }pr=r; 84 return Query(rt[pl-1],rt[pr],1,n,a,b-x+1); 85 } 86 87 int main(){ 88 freopen("heoi2016_str.in","r",stdin); 89 freopen("heoi2016_str.out","w",stdout); 90 scanf("%d%d%s",&n,&Q,s); 91 for(;s[len];len++)r[len]=s[len]; 92 DA(len+1,128);LCP(len);Prepare(len); 93 for(int i=1;i<=len;i++) 94 Insert(rt[i-1],rt[i],1,len,sa[i]+1,1); 95 while(Q--){ 96 scanf("%d%d%d%d",&a,&b,&c,&d); 97 lo=1,hi=min(b-a+1,d-c+1); 98 while(lo<=hi){ 99 int MID=(lo+hi)>>1; 100 if(Check(MID,len))lo=MID+1; 101 else hi=MID-1; 102 } 103 printf("%d\n",hi); 104 } 105 return 0; 106 }
尽最大的努力,做最好的自己!