bzoj1031: [JSOI2007]字符加密Cipher(后缀数组)
来源:互联网 发布:java导入进度条 编辑:程序博客网 时间:2024/06/06 18:15
题目传送门
题目挺不错的。
赤果果的后缀数组啊。
我好像只会后缀数组作后缀排名了。
真的菜。(我要变强!!)
因为他的字符串排成了一圈了。所以说我们应该长度为两倍才行。
比如:
abcd。
那么就会有四个串。
abcd,bcda,cdab,dabc。
这样很容易就可以看出我们应该把字符串变成:
abcdabc。
这样的话我们就会有这四个串了。
那么拿新的字符串去跑一遍后缀数组。
那么就会有2*len-1个后缀。len表示原串长度
那么有些字符串很明显要越界了。
所以我们只要不越界的字符串输出最后一个字符就OK了。
比如这个后缀的初始位置为i。
因为每个串的长度都应该为len。
那么我们就要判断i+len-1也就是这个串的结束位置是否越界(<=2*len-1)
然后把最后一个字符都输出出来就OK了吧。
代码实现:
#include<cstdio>#include<cstring>using namespace std;char s[1100000];int sa1[1100000],sa2[1100000],Rsort[1100000],Rank[1100000],a[1100000],tt[1100000];char ans[1110000];void solve(int n,int m) { for(int i=1;i<=n;i++) Rank[i]=a[i]; memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=n;i++) Rsort[Rank[i]]++; for(int i=1;i<=m;i++) Rsort[i]+=Rsort[i-1]; for(int i=n;i>=1;i--) sa1[Rsort[Rank[i]]--]=i; int p=0,ln=1; while(p<n) { int k=0; for(int i=n-ln+1;i<=n;i++) sa2[++k]=i; for(int i=1;i<=n;i++) if(sa1[i]-ln>0) sa2[++k]=sa1[i]-ln; memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=n;i++) Rsort[Rank[i]]++; for(int i=1;i<=m;i++) Rsort[i]+=Rsort[i-1]; for(int i=n;i>=1;i--) sa1[Rsort[Rank[sa2[i]]]--]=sa2[i]; for(int i=1;i<=n;i++) tt[i]=Rank[i]; p=1; Rank[sa1[1]]=1; for(int i=2;i<=n;i++) { if(tt[sa1[i]]!=tt[sa1[i-1]] || tt[sa1[i]+ln]!=tt[sa1[i-1]+ln]) p++; Rank[sa1[i]]=p; } m=p; ln*=2; } int len=0; for(int i=1;i<=n;i++) if(sa1[i]+n/2<=n) //这里本来写的是sa1[i]+n/2+1-1的,因为2*len-1很明显为基数,那么他除以2的话就会比原长度少1,那么要加上1,后面的-1就是加上长度之后-1的位置就是结尾。 ans[++len]=s[sa1[i]+n/2]; for(int i=1;i<=len;i++) printf("%c",ans[i]); printf("\n");}int main() { scanf("%s",s+1); int len=strlen(s+1); for(int i=1;i<=len-1;i++) //把字符串复制一遍 s[i+len]=s[i]; len*=2;len--; for(int i=1;i<=len;i++) a[i]=s[i]; solve(len,300); return 0;}
后缀数组有点玄学,初二的时候第一次学很懵13。
然而现在终于理解了,太开心了!
阅读全文
0 0
- [BZOJ1031][JSOI2007]字符加密Cipher && 后缀数组
- [JSOI2007] [BZOJ1031] 字符加密Cipher - 后缀数组
- BZOJ1031 [JSOI2007]字符加密Cipher 后缀数组
- [BZOJ1031][[JSOI2007]字符加密Cipher] 后缀数组
- BZOJ1031[JSOI2007]字符加密Cipher 后缀数组
- [bzoj1031][JSOI2007]字符加密Cipher 后缀数组
- [BZOJ1031][JSOI2007]字符加密Cipher(后缀数组)
- bzoj1031: [JSOI2007]字符加密Cipher(后缀数组)
- 【bzoj1031】【JSOI2007】【字符加密】【Cipher】【字符串】【后缀数组】
- 后缀数组 模板【JSOI2007】 bzoj1031 字符加密Cipher
- 【后缀数组】BZOJ1031(JSOI2007)[字符加密Cipher]题解
- 后缀数组——BZOJ1031 [JSOI2007]字符加密Cipher
- [BZOJ1031]-[JSOI2007]字符加密Cipher-后缀数组模板(附自己的理解)
- bzoj1031[JSOI2007]字符加密Cipher(拆环变链,利用sa数组)
- BZOJ1031: [JSOI2007]字符加密Cipher
- [Bzoj1031][JSOI2007]字符加密Cipher
- [bzoj1031][JSOI2007]字符加密Cipher
- [BZOJ1031][JSOI2007]字符加密Cipher
- L1-039. 古风排版
- jQuery常用技巧及常用方法列表集合
- bzoj4518 [Sdoi2016]征途(斜率优化dp)
- 数据库函数总结(Oracle篇二)
- Roman to Integer
- bzoj1031: [JSOI2007]字符加密Cipher(后缀数组)
- python字典快速保存于读取
- Mac中设置docker命令行自动补全的方法
- Netty源码分析:服务端启动全过程(篇幅很长)
- Vue之生命周期
- UICC之UiccCardApplication
- PHP页面和Mysql数据库的转UTF8编码问题总结
- tensorflow安装:“ModuleNotFoundError: No module named '_pywrap_tensorflow_internal'”
- 矩阵元素查找