P2870 [USACO07DEC]最佳牛線,黃金Best Cow Line, Gold 解題報告
阿新 • • 發佈:2018-12-15
best include -- 題意 解題報告 amp algo -i 報告
P2870 [USACO07DEC]最佳牛線,黃金Best Cow Line, Gold
題意
給一個字符串,每次可以從兩邊中的一邊取一個字符,要求取出的字符串字典序最小
可以Hash+二分
也可以SA
首先貪心選字典序小的
然後遇到相等的了比Rank數組,把原串倍長一下就可以比了。
Code:
#include <cstdio> #include <algorithm> const int N=6e4+10; char s[N],ans[N]; int sa[N],Rank[N],tax[N],sec[N],n,m,cnt; void Rsort() { for(int i=0;i<=m;i++) tax[i]=0; for(int i=1;i<=n;i++) ++tax[Rank[i]]; for(int i=1;i<=m;i++) tax[i]+=tax[i-1]; for(int i=n;i;i--) sa[tax[Rank[sec[i]]]--]=sec[i]; } bool cmp(int x,int y,int len){return sec[x]==sec[y]&&sec[x+len]==sec[y+len];} void SuffixSort() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("\n%c",s+i),s[(n<<1)+1-i]=s[i]; n<<=1; for(int i=1;i<=n;i++) Rank[i]=s[i]+1-'A',sec[i]=i; m=26,Rsort(); for(int p=0,w=1;p<n;w<<=1,m=p) { p=0;for(int i=n-w+1;i<=n;i++) sec[++p]=i; for(int i=1;i<=n;i++) if(sa[i]>w) sec[++p]=sa[i]-w; Rsort(),std::swap(Rank,sec),Rank[sa[1]]=p=1; for(int i=2;i<=n;i++) Rank[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p; } n>>=1; } int main() { SuffixSort(); int l=1,r=n; while(l<=r) { if(s[l]>s[r]) ans[++cnt]=s[r--]; else if(s[l]<s[r]) ans[++cnt]=s[l++]; else { if(Rank[l]<Rank[n*2-r+1]) ans[++cnt]=s[l++]; else ans[++cnt]=s[r--]; } } for(int i=1;i<=cnt;i++) { putchar(ans[i]); if(i%80==0) puts(""); } return 0; }
2018.12.15
P2870 [USACO07DEC]最佳牛線,黃金Best Cow Line, Gold 解題報告