jzoj1247-队列变换【字符串hash,二分】
生活随笔
收集整理的這篇文章主要介紹了
jzoj1247-队列变换【字符串hash,二分】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://jzoj.net/senior/#main/show/1247
題目大意
一個長度為nnn的字符串,每次選擇頭或者尾加入新的字符串末端,求字典序最小的新的字符串。
解題思路
我們發現若剩下的字符串比翻轉之后份字符串字典序大那么就加入頭,否則就加入尾。所以我們之間判定就是O(n2)O(n^2)O(n2)的,但是這樣的時間復雜度不夠優秀。
我們考慮字符串hashhashhash,比較字典序要找到第一個不同的位置,我們二分一下那個位置字符串hashhashhash判定即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define ull unsigned long long using namespace std; const int N=31000; const ull p=13331; int n,z;char c[N]; ull f[N],g[N],pow[N]; ull getf(int l,int r) {return f[r]-f[l-1]*pow[r-l+1];} ull getg(int l,int r) {return g[l]-g[r+1]*pow[r-l+1];} int main() {scanf("%d",&n);pow[0]=1;for(int i=1;i<=n;i++)cin>>c[i],pow[i]=pow[i-1]*p;for(int i=1;i<=n;i++)f[i]=f[i-1]*p+c[i]-'A'+1;for(int i=n;i>=1;i--)g[i]=g[i+1]*p+c[i]-'A'+1;int L=1,R=n;for(int i=1;i<=n;i++){int l=0,r=R-L;while(l<=r){int mid=(l+r)/2;if(getf(L,L+mid)==getg(R-mid,R)) l=mid+1;else r=mid-1;}if(c[L+l]<c[R-l]) putchar(c[L++]);else putchar(c[R--]);z++;if(z%80==0) putchar('\n');} }總結
以上是生活随笔為你收集整理的jzoj1247-队列变换【字符串hash,二分】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑刷抖音的正确姿势电脑刷抖音的方法
- 下一篇: 牛客-无形的博弈【结论题,快速幂】