BZOJ4278 : [ONTAK2015]Tasowanie
首先在串的末尾加上1000,然后进行归并,每次取字典序较小的那个后缀即可。
用hash+二分支持查询lcp,时间复杂度O(nlogn)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include<cstdio> typedef long long ll; const int N=200010,P=31,D=1000173169; int n,m,i,j,k, pow [N],a[N],b[N],f[N],g[N]; inline void read( int &a){ char c; while (!(((c= getchar ())>= '0' )&&(c<= '9' )));a=c- '0' ; while (((c= getchar ())>= '0' )&&(c<= '9' ))(a*=10)+=c- '0' ;} inline int hash0( int l, int r){ return (ll)(f[r]-(ll)f[l-1]* pow [r-l+1]%D+D)%D;} inline int hash1( int l, int r){ return (ll)(g[r]-(ll)g[l-1]* pow [r-l+1]%D+D)%D;} inline int ask( int a, int b){ int l=1,r=n-a+1,mid,t=0; if (m-b+1<r)r=m-b+1; while (l<=r){ mid=(l+r)>>1; if (hash0(a,a+mid-1)==hash1(b,b+mid-1))l=(t=mid)+1; else r=mid-1; } return t; } int main(){ for ( pow [0]=i=1;i<N;i++) pow [i]=(ll) pow [i-1]*P%D; for (read(n),i=1;i<=n;i++)read(a[i]),f[i]=((ll)f[i-1]*P+a[i])%D; for (read(m),i=1;i<=m;i++)read(b[i]),g[i]=((ll)g[i-1]*P+b[i])%D; for (a[n+1]=b[m+1]=1000,i=j=1;i<=n&&j<=m; printf ( "%d " ,a[i+k]<b[j+k]?a[i++]:b[j++]))k=ask(i,j); while (i<=n) printf ( "%d " ,a[i++]); while (j<=m) printf ( "%d " ,b[j++]); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步