bzoj-1031 字符加密Cipher
生活随笔
收集整理的這篇文章主要介紹了
bzoj-1031 字符加密Cipher
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題意:
給出一個(gè)字符串,求將其所有循環(huán)串排序之后,每個(gè)串的最后一個(gè)字符;
字符串長度<=100000;
題解:
后綴數(shù)組裸題。。吧
學(xué)長拿這個(gè)當(dāng)例題我還差點(diǎn)不會做。。。
反正就是把字符串倍增之后求后綴數(shù)組;
然后按后綴數(shù)組來掃一遍求解;
難點(diǎn)就是后綴排序(廢話!);
這里用的是O(nlogn)的倍增+基數(shù)排序方法;
模板純手寫。。一堆for循環(huán)也是有毒。。
原理上就是利用倍增的思想,將每次的排序轉(zhuǎn)化為二元組的排序問題;
而二元組的排序問題可以利用基數(shù)排序O(n)解決而已;
寫代碼的時(shí)候好費(fèi)勁啊。。。碼力果然不夠強(qiáng);
30行模板4數(shù)組,Orz PoPoQQQ 60行SA;
代碼:
#include<stdio.h> #include<string.h> #include<algorithm> #define N 210000 #define S 256 using namespace std; char str[N]; int rank[N],tr[N],hash[N],sa[N]; int main() {int n,m,j,k,cnt;register int i;scanf("%s",str);n=strlen(str);memcpy(str+n,str,sizeof(char)*n);n<<=1;for(i=0;i<n;i++) hash[str[i]]++;for(i=1,cnt=0;i<S;i++) if(hash[i]) tr[i]=++cnt;for(i=1;i<S;i++) hash[i]=hash[i-1]+hash[i];for(i=0;i<n;i++) rank[i]=tr[str[i]];for(i=0;i<n;i++) sa[--hash[str[i]]]=i;for(k=2;k<=n;k<<=1){memset(hash,0,sizeof(hash));for(i=0;i<n;i++) hash[rank[i]]++;for(i=1;i<=n;i++) hash[i]=hash[i]+hash[i-1];for(i=n-1;i>=0;i--) if(sa[i]>=(k>>1))tr[sa[i]-(k>>1)]=--hash[rank[sa[i]-(k>>1)]];for(i=1;i<=(k>>1);i++) tr[n-i]=--hash[rank[n-i]];for(i=0;i<n;i++) sa[tr[i]]=i;for(i=1,cnt=0;i<n;i++)if(rank[sa[i-1]]==rank[sa[i]]&&rank[sa[i-1]+(k>>1)]==rank[sa[i]+(k>>1)]) tr[sa[i]]=tr[sa[i-1]];else tr[sa[i]]=++cnt;memcpy(rank,tr,sizeof(tr));if(cnt==n-1)break;}for(i=0;i<n;i++){if(sa[i]<(n>>1))printf("%c",str[sa[i]+(n>>1)-1]);}return 0; }
總結(jié)
以上是生活随笔為你收集整理的bzoj-1031 字符加密Cipher的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: editor上传视频无法播放的问题
- 下一篇: 【springboot整合多数据源】