当我年少轻狂时,我曾拥有自由,但我并不明白它的意义。我曾拥有时间,但我没有意识到它的珍贵。我曾拥有爱,但我从未用心去体会。数十年的时间考验后,我终于理解了三者的真谛。 我已风烛残年,这种理解已经逐渐变成一种满足。爱,自由和时间,曾一度被我挥霍,而今成为了我前进的动力。而我将最特别的爱,献给最亲爱的你和我们的孩子们,以及刺客联盟的兄弟姐妹们,并献给赋予我们生命的那壮美奇妙,让人产生无限遐想的世界。此爱永恒,Mia Sofia。永远都属于你的--艾吉奥·奥迪托雷。——刺客信条:余烬
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<bits/stdc++.h> using namespace std; #define Ri register const int N=4e5+10; int n,m,tot,len; int r[N],sa[N],ranki[N],height[N],wa[N],wb[N],wv[N],wt[N]; char s[N]; inline int cmp(int *y,int a,int b,int k){ return y[a]==y[b]&&(a+k>=n?-1:y[a+k])==(b+k>=n?-1:y[b+k]); /*if(y[a]!=y[b])return 0; if((a+k<n)^(b+k<n))return 0; if(a+k<n&&b+k<n)return y[a+k]==y[b+k];*/ return 0; } inline void SA(int *r,int *sa,int n,int m){ int p=1,*x=wa,*y=wb,*t; m=400; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[x[i]]]=i; for(Ri int j=1;j<n;j<<=1){ p=0; for(Ri int i=n-j;i<n;i++)y[p++]=i; for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; //cout<<"y "<<endl; //for(Ri int i=0;i<p;i++)cout<<y[i]<<" ";cout<<endl; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)wv[i]=x[y[i]]; for(Ri int i=0;i<n;i++)++wt[wv[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; /*cout<<"wv "<<endl; for(Ri int i=0;i<n;i++)cout<<wv[i]<<" ";cout<<endl; cout<<"wt "<<endl; for(Ri int i=0;i<n;i++)cout<<wt[i]<<" ";cout<<endl;*/ for(Ri int i=n-1;i>=0;i--)sa[--wt[wv[i]]]=y[i]; p=0; t=x;x=y;y=t; x[sa[0]]=0; for(Ri int i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p; /*cout<<"sa "<<endl; for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl; cout<<"ranki "<<endl; for(Ri int i=0;i<n;i++)cout<<x[i]<<" ";cout<<endl;*/ m=p+1; if(p>n-2)break; } for(Ri int i=0;i<n;i++)ranki[sa[i]]=i; /*cout<<"sa "<<endl; for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl; cout<<"ranki "<<endl; for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl;*/ } inline bool check(int id){ for(Ri int i=0;i<len;i++){ int now=i; for(Ri int j=0;j<tot;j++){ now+=len-(ranki[now]>id); if(now-i>=n)return true; } } return false; } signed main(){ cin>>n>>tot;scanf("%s",s); len=n/tot+(n%tot!=0); for(Ri int i=0;i<n;i++)s[i+n]=s[i]; n<<=1; for(Ri int i=0;i<n;i++)r[i]=s[i];//,cout<<s[i];cout<<endl; SA(r,sa,n,m); int L=0,R=n-1,mid; n>>=1; while(L<R){ mid=(L+R)>>1; //cout<<"L "<<L<<" R "<<R<<" mid "<<mid<<endl; if(check(mid))R=mid; else L=mid+1; } //cout<<R<<endl; for(Ri int i=0;i<(n<<1);i++)if(ranki[i]==R) for(Ri int j=0;j<len;j++)cout<<s[j+i]; return 0; } /* 4 2 4321 ans 32 */
https://www.luogu.com.cn/problem/P3181
新版思路:比较不能用-1,那就全部向右平移,只要把m开得够大就行。
#include<bits/stdc++.h> using namespace std; #define Ri register const int N=4e5+10; const int inf=0x3f3f3f3f; int n,m,r[N],sa[N],ranki[N],height[N],wa[N],wb[N],wv[N],wt[N]; int f[N][20],lens,lent,logi[N]; char s[N],t[N]; inline int cmp(int *r,int a,int b,int k){ return r[a]==r[b]&&(a+k<n?r[a+k]:-1)==(b+k<n?r[b+k]:-1); //return r[a]==r[b]&&r[a+k]==r[b+k]; } inline void SA(int *r,int *sa,int n,int m){ int *x=wa,*y=wb,*t; int p=1; m=400; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[x[i]]]=i; for(Ri int j=1;j<n;j<<=1,m=p){ p=0; for(Ri int i=n-j;i<n;i++)y[p++]=i; for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)wv[i]=x[y[i]]; for(Ri int i=0;i<n;i++)++wt[wv[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[wv[i]]]=y[i]; p=1;t=x;x=y;y=t;x[sa[0]]=0; for(Ri int i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; m=p; if(p>=n)break; } /*cout<<"sa "<<endl; for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;*/ } inline void calc(int *r,int *sa,int n){ int k=0,j; for(Ri int i=0;i<n;i++)ranki[sa[i]]=i; height[0]=0; for(Ri int i=0;i<n;i++){ if(ranki[i]==0)continue; if(k)--k; j=sa[ranki[i]-1]; while(i+k<n&&j+k<n&&r[i+k]==r[j+k])++k; height[ranki[i]]=k; } /*cout<<"ranki "<<endl; for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl; cout<<"height "<<endl; for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;*/ } inline int query(int l,int r){ if(l>r)swap(l,r);++l; int k=logi[r-l+1]; return min(f[l][k],f[r-(1<<k)+1][k]); } signed main(){ memset(f,inf,sizeof(f)); scanf("%s%s",s,t); lens=strlen(s);lent=strlen(t); for(Ri int i=0;i<lens;i++)r[i]=s[i]+5; r[lens]=4; for(Ri int i=0;i<lent;i++)r[i+lens+1]=t[i]+5; n=lens+lent+1; r[n++]=0; /*cout<<"r "<<endl; for(Ri int i=0;i<n;i++)cout<<r[i]<<" ";cout<<endl;*/ SA(r,sa,n,m);calc(r,sa,n); logi[0]=logi[1]=0;logi[2]=1; for(Ri int i=3;i<=n;i++)logi[i]=logi[i/2]+1; /*cout<<"logi "<<endl; for(Ri int i=0;i<n;i++)cout<<logi[i]<<" ";cout<<endl;*/ for(Ri int i=1;i<n;i++)f[i][0]=height[i]; /*cout<<"before r "<<endl; for(Ri int i=0;i<n;i++)cout<<(char)r[i];cout<<endl; //--n; cout<<"after r "<<endl; for(Ri int i=0;i<n;i++)cout<<(char)r[i];cout<<endl;*/ for(Ri int i=1;i<=18;i++) for(Ri int j=1;j+(1<<i)-1<n;j++) f[j][i]=min(f[j][i-1],f[j+(1<<(i-1))][i-1]); /*cout<<"f "<<endl; for(Ri int i=1;i<n;i++){ for(Ri int j=0;j<=10;j++)cout<<f[i][j]<<" "; cout<<endl; }*/ int ans=0; for(Ri int i=0;i<lens;i++){ for(Ri int j=lens+1;j<n;j++){ int lcp=query(ranki[i],ranki[j]); //cout<<"L "<<ranki[i]<<" R "<<ranki[j]<<" lcp "<<lcp<<endl; ans+=lcp; } } cout<<ans; return 0; }
我的代码丑得难以直视……心塞……
来自
https://www.luogu.com.cn/blog/boshi/solution-p3181
#include <iostream> #include <cstring> #include <cstdio> #define MX 823123 using namespace std; typedef long long ll; typedef struct tSA { int str[MX],n,m; int rank[MX],SA[MX],het[MX]; int buk[MX],yp[MX]; bool cmp(int *f,int x,int y,int w){return f[x]==f[y]&&f[x+w]==f[y+w];} void jsort() { for(int i=0;i<=m;i++)buk[i]=0; for(int i=1;i<=n;i++)buk[rank[yp[i]]]++; for(int i=1;i<=m;i++)buk[i]+=buk[i-1]; for(int i=n;i>=1;i--)SA[buk[rank[yp[i]]]--]=yp[i]; } void getSA() { for(int i=1;i<=n;i++)rank[i]=str[i],yp[i]=i; m=28;jsort(); for(int w=1;w<n;w<<=1) { int p=0; for(int i=n-w+1;i<=n;i++)yp[++p]=i; for(int i=1;i<=n;i++)if(SA[i]>w)yp[++p]=SA[i]-w; jsort(),swap(rank,yp),rank[SA[1]]=p=1; for(int i=2;i<=n;i++)rank[SA[i]]=(cmp(yp,SA[i],SA[i-1],w)?p:++p); m=p; } int k=0; for(int i=1;i<=n;i++) { k=(k?k-1:0); while(str[i+k]==str[SA[rank[i]-1]+k])k++; het[rank[i]]=k; } } }SA; SA sa; char str[MX]; int l1,l2,top,sum[MX]; pair<int,ll>stk[MX]; void work() { ll ans=0; stk[0]=make_pair(1,0); for(int i=1;i<=sa.n;i++)sum[i]=sum[i-1]+(sa.SA[i]<=l1); for(int i=1;i<=sa.n;i++) { while(top&&sa.het[stk[top].first]>sa.het[i])top--; top++; stk[top]=make_pair(i,(sum[i-1]-sum[stk[top-1].first-1])*sa.het[i]+stk[top-1].second); if(sa.SA[i]>l1+1)ans+=stk[top].second; } top=0; for(int i=1;i<=sa.n;i++)sum[i]=sum[i-1]+(sa.SA[i]>l1+1); for(int i=1;i<=sa.n;i++) { while(top&&sa.het[stk[top].first]>sa.het[i])top--; top++; stk[top]=make_pair(i,(sum[i-1]-sum[stk[top-1].first-1])*sa.het[i]+stk[top-1].second); if(sa.SA[i]<=l1)ans+=stk[top].second; } printf("%lld\n",ans); } int main() { scanf("%s",str+1);l1=strlen(str+1); scanf("%s",str+l1+2); str[l1+1]='z'+1; sa.n=strlen(str+1); for(int i=1;i<=sa.n;i++)sa.str[i]=str[i]-'a'+1; sa.getSA(); work(); return 0; }
https://www.luogu.com.cn/problem/P5546
这次ub是因为没有把数组初始化。
#include<bits/stdc++.h> using namespace std; #define int long long #define Ri register const int N=1e5+100; int T,n,m,r[N],sa[N],ranki[N],height[N],wa[N],wb[N],wv[N],wt[N]; int color[N]; char s[N]; inline int cmp(int *r,int a,int b,int k){ return r[a]==r[b]&&(a+k<n?r[a+k]:-1)==(b+k<n?r[b+k]:-1); //return r[a]==r[b]&&r[a+k]==r[b+k]; } inline void SA(int *r,int *sa,int n,int m){ int *x=wa,*y=wb,*t; int p=1; m=400; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[x[i]]]=i; for(Ri int j=1;j<n;j<<=1,m=p){ p=0; for(Ri int i=n-j;i<n;i++)y[p++]=i; for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)wv[i]=x[y[i]]; for(Ri int i=0;i<n;i++)++wt[wv[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[wv[i]]]=y[i]; p=1;t=x;x=y;y=t;x[sa[0]]=0; for(Ri int i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; m=p; if(p>=n)break; } /*cout<<"sa "<<endl; for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;*/ } inline void calc(int *r,int *sa,int n){ int k=0,j; for(Ri int i=0;i<n;i++)ranki[sa[i]]=i; height[0]=0; for(Ri int i=0;i<n;i++){ if(ranki[i]==0)continue; if(k)--k; j=sa[ranki[i]-1]; while(i+k<n&&j+k<n&&r[i+k]==r[j+k])++k; height[ranki[i]]=k; } /*cout<<"ranki "<<endl; for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl; cout<<"height "<<endl; for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;*/ } inline bool check(int minn){ int vis[110]; memset(vis,0,sizeof(vis)); for(Ri int i=2;i<n;i++){ if(height[i]<minn){ int flag=0; for(Ri int j=1;j<=T;j++)flag+=vis[j]; if(flag==T)return true; memset(vis,0,sizeof(vis)); }else{ if(height[i-1]<minn)vis[color[i-1]]=1; vis[color[i]]=1; } } return false; } signed main(){ cin>>T; int maxn=0; for(Ri int i=1;i<=T;i++){ scanf("%s",s+n); for(Ri int j=n;j<(int)strlen(s);j++)color[j]=i; maxn=max(maxn,(int)strlen(s)-n); n=strlen(s); } //for(Ri int i=0;i<n;i++)cout<<s[i];cout<<endl; //for(Ri int i=0;i<n;i++)cout<<color[i]<<" ";cout<<endl; n=0; for(Ri int i=0;i<(int)strlen(s);i++){ r[n++]=s[i]+5; if(color[i]+1==color[i+1])r[n++]=4; } r[n++]=0; //for(Ri int i=0;i<n;i++)cout<<i<<" "<<(char)r[i]<<endl; memset(color,0,sizeof(color)); SA(r,sa,n,m);calc(r,sa,n); for(Ri int i=0,j=1;i<n-1;i++){ if(r[i]==4)++j; color[ranki[i]]=j; } /*cout<<"color "<<endl; for(Ri int i=0;i<=n;i++)cout<<color[i]<<" ";cout<<endl; cout<<check(1)<<" "<<check(2)<<" "<<check(3)<<endl;*/ int L=0,R=maxn+1,mid=0,ans=0; while(L<R){ mid=(L+R)/2; //cout<<"L "<<L<<" R "<<R<<" mid "<<mid<<endl; if(check(mid))L=mid,ans=mid; else R=mid-1; //cout<<mid<<endl; } cout<<ans; return 0; } /* 3 abcb bca acbc */
#include<bits/stdc++.h> using namespace std; #define int long long #define Ri register const int N=1e5+100; int T,n,m,r[N],sa[N],ranki[N],height[N],wa[N],wb[N],wv[N],wt[N]; int color[N]; char s[N],t[10][2010]; char temp[10] = {'!', '@', '#', '$', 0}; inline int cmp(int *r,int a,int b,int k){ return r[a]==r[b]&&(a+k<n?r[a+k]:-1)==(b+k<n?r[b+k]:-1); //return r[a]==r[b]&&r[a+k]==r[b+k]; } inline void SA(int *r,int *sa,int n,int m){ int *x=wa,*y=wb,*t; int p=1; m=400; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)++wt[x[i]=r[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[x[i]]]=i; for(Ri int j=1;j<n;j<<=1,m=p){ p=0; for(Ri int i=n-j;i<n;i++)y[p++]=i; for(Ri int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(Ri int i=0;i<m;i++)wt[i]=0; for(Ri int i=0;i<n;i++)wv[i]=x[y[i]]; for(Ri int i=0;i<n;i++)++wt[wv[i]]; for(Ri int i=1;i<m;i++)wt[i]+=wt[i-1]; for(Ri int i=n-1;i>=0;i--)sa[--wt[wv[i]]]=y[i]; p=1;t=x;x=y;y=t;x[sa[0]]=0; for(Ri int i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; m=p; if(p>=n)break; } /*cout<<"sa "<<endl; for(Ri int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;*/ } inline void calc(int *r,int *sa,int n){ int k=0,j; for(Ri int i=0;i<n;i++)ranki[sa[i]]=i; height[0]=0; for(Ri int i=0;i<n;i++){ if(ranki[i]==0)continue; if(k)--k; j=sa[ranki[i]-1]; while(i+k<n&&j+k<n&&r[i+k]==r[j+k])++k; height[ranki[i]]=k; } /*cout<<"ranki "<<endl; for(Ri int i=0;i<n;i++)cout<<ranki[i]<<" ";cout<<endl; cout<<"height "<<endl; for(Ri int i=0;i<n;i++)cout<<height[i]<<" ";cout<<endl;*/ }/* inline bool check(int minn){ int vis[110]; memset(vis,0,sizeof(vis)); for(Ri int i=2;i<n;i++){ if(height[i]<minn){ int flag=0; for(Ri int j=1;j<=T;j++)flag+=vis[j]; if(flag==T)return true; memset(vis,0,sizeof(vis)); }else{ if(height[i-1]<minn)vis[color[i-1]]=1; vis[color[i]]=1; } } return false; }*/ inline bool check(int mid){ int vis[10]; memset(vis,0,sizeof(vis)); for(Ri int i=2;i<n;i++){ if(height[i]>=mid)vis[color[sa[i]]]=1; else{ int flag=0; for(Ri int j=1;j<=T;j++){ if(!vis[j])flag=1; vis[j]=0; } if(!flag)return true; vis[color[sa[i]]]=1; } } int flag=0; for(Ri int i=1;i<=T;i++){ if(!vis[i])flag=1; vis[i]=0; } if(!flag)return true; else return false; } signed main(){ cin>>T; int maxn=0; n=0; for(Ri int i=1;i<=T;i++){ scanf("%s",t[i]); maxn=max(maxn,(int)strlen(t[i])); for(Ri int j=0;j<(int)strlen(t[i]);j++)color[n]=i,s[n++]=t[i][j]; if(i!=T)s[n++]=i; } //for(Ri int i=0;i<n;i++)cout<<s[i];cout<<endl; //for(Ri int i=0;i<n;i++)cout<<color[i]<<" ";cout<<endl; /*n=0; for(Ri int i=0,j=0;i<(int)strlen(s);i++){ r[n++]=s[i]+5; if(color[i]+1==color[i+1])r[n++]=temp[j++]; }*/ r[n++]=0; for(Ri int i=0;i<n;i++)r[i]=s[i];//,cout<<(char)r[i];cout<<endl; //for(Ri int i=0;i<n;i++)cout<<i<<" "<<(char)r[i]<<endl; //memset(color,0,sizeof(color)); SA(r,sa,n,m);calc(r,sa,n); /*for(Ri int i=0,j=1;i<n-1;i++){ if(r[i]==(int)temp[j-1])++j; color[ranki[i]]=j; } cout<<"color "<<endl; for(Ri int i=0;i<=n;i++)cout<<color[i]<<" ";cout<<endl;*/ //cout<<check(1)<<" "<<check(2)<<" "<<check(3)<<endl; int L=0,R=n,mid=0,ans=0; while(L+1<R){ mid=(L+R)/2; //cout<<"L "<<L<<" R "<<R<<" mid "<<mid<<endl; if(check(mid))L=mid; else R=mid; //cout<<mid<<endl; } if(check(R))ans=R; else ans=L; cout<<ans; return 0; } /* 3 abcb bca acbc */