首页 > 代码库 > 51nod-1732 婚姻介绍所(后缀数组)
51nod-1732 婚姻介绍所(后缀数组)
题目大意:回答任意两个子串的最长公共前缀。
题目分析:后缀数组的模板题。但是输入输出都要外挂。
代码如下:
# include<iostream># include<cstdio># include<cstring># include<algorithm>using namespace std;const int N=1000;int n,m;char s[N+5];int cnt[N+5],SA[N+5];int rk[N+5],tSA[N+5];int height[N+5];int ans[N+5][N+5];void in(int &x){ x=0; char c=getchar(); while(c<‘0‘||c>‘9‘){ c=getchar(); } x=c-‘0‘; while(c=getchar()){ if(c<‘0‘||c>‘9‘) break; x=x*10+c-‘0‘; }}void out(int x){ if(x>=10) out(x/10); putchar(x%10+‘0‘);}bool same(int *y,int i,int j,int k){ if(y[SA[i]]!=y[SA[j]]) return false; if(SA[i]+k>=n&&SA[j]+k>=n) return true; if(SA[i]+k<n&&SA[j]+k>=n) return false; if(SA[i]+k>=n&&SA[j]+k<n) return false; return y[SA[i]+k]==y[SA[j]+k];}void buildSA(){ m=130; int *x=rk,*y=tSA; for(int i=0;i<m;++i) cnt[i]=0; for(int i=0;i<n;++i) ++cnt[x[i]=s[i]]; for(int i=1;i<m;++i) cnt[i]+=cnt[i-1]; for(int i=n-1;i>=0;--i) SA[--cnt[x[i]]]=i; for(int k=1;k<=n;k<<=1){ int p=0; for(int i=n-k;i<n;++i) y[p++]=i; for(int i=0;i<n;++i) if(SA[i]>=k) y[p++]=SA[i]-k; for(int i=0;i<m;++i) cnt[i]=0; for(int i=0;i<n;++i) ++cnt[x[y[i]]]; for(int i=1;i<m;++i) cnt[i]+=cnt[i-1]; for(int i=n-1;i>=0;--i) SA[--cnt[x[y[i]]]]=y[i]; p=1; swap(x,y); x[SA[0]]=0; for(int i=1;i<n;++i){ if(same(y,i,i-1,k)) x[SA[i]]=p-1; else x[SA[i]]=p++; } if(p>=n) break; m=p; }}void getHeight(){ for(int i=0;i<n;++i) rk[SA[i]]=i; height[0]=0; for(int i=1;i<n;++i){ int k=0; while(s[SA[i]+k]==s[SA[i-1]+k]) ++k; height[i]=k; }}void getAns(){ for(int i=0;i<n;++i) ans[i][i]=n-i; for(int i=0;i<n;++i){ int minn=n; for(int j=i+1;j<n;++j){ minn=min(minn,height[j]); ans[SA[i]][SA[j]]=ans[SA[j]][SA[i]]=minn; } }}int main(){ int q,a,b; while(~scanf("%d",&n)) { scanf("%s",s); buildSA(); getHeight(); getAns(); in(q); while(q--) { in(a); in(b); out(ans[a][b]); puts(""); } } return 0;}
51nod-1732 婚姻介绍所(后缀数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。