后缀数组(bzoj 1031: [JSOI2007]字符加密Cipher)
后缀数组主要功能:
长度为n的字符串总共有n个后缀,求这n个后缀的字典序
实现方法:倍增+基数排序,过程就是下面那张表
求log(n)次rank数组,每次的rank数组都可以通过上次的rank数组得出
最后的rank就是答案,过程看起来简单,但代码实现挺难得!
Rank[]:rank[i]=p表示下标为i开头的字符串排第p个
Sa[]:Sa[i]=p表示排第i个的字符串是下标为p开头的字符串
cot[]:辅助数组,cot[i]=p表示当前rank数组中值小于等于i的数的个数
例如rank[]:{1,2,4,1,1,1,2,3},那么cot[1]==4,cor[2]==6,cot[3]==7,cot[4]==8
(或初始字符串中ASCLL码<=i的字符个数)
Temp[]:Temp[i]=p意思就是第二个数(图里y数组)中第i的小的是下标p上的数
参考博文:
http://www.cnblogs.com/shanchuan04/p/5324009.html
http://blog.csdn.net/yxuanwkeith/article/details/50636898
http://blog.csdn.net/qq_34731703/article/details/52934284
代码中有注释
1031: [JSOI2007]字符加密Cipher
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 7202 Solved: 3120
[Submit][Status][Discuss]
Description
Input
输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。
Output
输出一行,为加密后的字符串。
Sample Input
Sample Output
题解:裸的后缀数组,因为是个环不是个后缀所以要将字符串复制一遍接在后面
然后就是模板
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char str[200100];
int a[200100], Rank[200100], Temp[200100], cot[200100], Sa[200100];
int main(void)
{int n, i, m, p, k;while(scanf("%s", str+1)!=EOF){n = strlen(str+1);for(i=1;i<=n;i++){a[i] = a[i+n] = str[i];str[i+n] = str[i];}n *= 2, m = 128;memset(cot, 0, sizeof(cot));for(i=1;i<=n;i++){Rank[i] = a[i];cot[a[i]]++;}for(i=1;i<=m;i++)cot[i] += cot[i-1]; // cot[i]表示ASCLL码小于等于i的字符个数for(i=n;i>=1;i--)Sa[cot[a[i]]--] = i;/*puts(str+1);for(i=1;i<=n;i++)printf("%d ", Sa[i]); // 第一次排序,输入ABAAB,输出结果为:printf("\n"); // ABAABABAABfor(i=1;i<=n;i++) // 1 3 4 6 8 9 2 5 7 10printf("%d ", Rank[i]); // 97 98 97 97 98 97 98 97 97 98printf("\n");*/for(k=1;k<=n;k*=2){p = 0;for(i=n-k+1;i<=n;i++) //下标在[n+1, n+k]范围内的字符是空字符,所以字典序肯定是最小的Temp[++p] = i;for(i=1;i<=n;i++) //前k个字符因为不参与排序,后面所有字符自动向前面移动k位(下标-k){if(Sa[i]>k)Temp[++p] = Sa[i]-k;}/*printf("k=%d\nTemp: ", k);for(i=1;i<=n;i++) // 当k=1时,输出结果为:printf("%d ", Temp[i]); // 10 2 3 5 7 8 1 4 6 9printf("\n");*/memset(cot, 0, sizeof(cot));for(i=1;i<=n;i++) /*这个时候,可以把rank当成新的a数组,之前的数组已经毫无意义*/cot[Rank[i]]++;for(i=1;i<=m;i++)cot[i] += cot[i-1];for(i=n;i>=1;i--)Sa[cot[Rank[Temp[i]]]--] = Temp[i];/* Temp[i]=p意思就是第二个数(图里y数组)中第i的大的是下标p上的数*/swap(Rank, Temp);p = 1;Rank[Sa[1]] = 1; //求出当前的rank数组,在这里之前的rank数组就已经毫无意义了for(i=2;i<=n;i++){if(Temp[Sa[i-1]]==Temp[Sa[i]] && Temp[Sa[i-1]+k]==Temp[Sa[i]+k])Rank[Sa[i]] = p;elseRank[Sa[i]] = ++p;}m = p;/*printf("Rank: ");for(i=1;i<=n;i++) // 当k=1时,输出结果为:printf("%d ", Rank[i]); // 2 4 1 2 4 2 4 1 2 3printf("\n");*/}n /= 2;for(i=1;i<=2*n;i++){if(Sa[i]>n)continue;printf("%c", str[Sa[i]+n-1]);}printf("\n");}
}
后缀数组(bzoj 1031: [JSOI2007]字符加密Cipher)相关推荐
- BZOJ 1031: [JSOI2007]字符加密Cipher( 后缀数组 )
为什么我的后缀数组跑得这么慢... 把字符串复制一遍放在最后, 然后跑sa, 扫一遍就行了... --------------------------------------------------- ...
- bzoj 1031 [JSOI2007]字符加密Cipher 后缀数组
题面 题目传送门 解法 后缀数组模板题吧-- 将字符串两倍,然后求一遍sa数组即可 时间复杂度:\(O(n\ log\ n)\) 代码 #include <bits/stdc++.h> # ...
- 【BZOJ】1031: [JSOI2007]字符加密Cipher(后缀数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1031 很容易想到这就是将字符串复制到自己末尾然后后缀数组搞出sa然后按区间输出即可. 然后换了下模板 ...
- BZOJ1031: [JSOI2007]字符加密Cipher
1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec Memory Limit: 162 MB Submit: 7882 Solved: 3425 [Subm ...
- [bzoj1031][JSOI2007]字符加密Cipher
1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4175 Solved: 1694 [Submit ...
- 【BZOJ1031】[JSOI2007]字符加密Cipher 后缀数组
[BZOJ1031][JSOI2007]字符加密Cipher Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的 ...
- 【BZOJ 1031】[JSOI2007]字符加密Cipher(后缀数组模板)
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1031 [题意] [题解] 后缀数组模板题; 把整个字符串扩大一倍. 即长度乘2 然后搞 ...
- bzoj1031 [JSOI2007]字符加密 后缀数组改
DA后缀数组构造的思想主要的就是倍增 即类似RMQ的双关键字排序 所以就可以用双关键字排序的方法来构造后缀数组 基数排序和快排都可以,鉴于是1e5,直接nlogn就够了 码: #include< ...
- [JSOI2007]字符加密
题目描述 喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法. 例如'JSOI07',可以读作 ...
最新文章
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序
- 解决IDEA使用lombok注解无效,@Data不生效问题
- 《精通Nginx》——2.3 使用include文件
- 自定义Checkbox让复选框居中对于RadioButton同样适用
- phpize增加php模块
- CF451E-Devu and Flowers【组合计数,容斥】
- vbox虚拟机配置Redhat6.4本地yum源
- 利用处理程序错误***(下)
- 关于Myeclipse10的激活
- Servlet读取xml文件的配置参数
- css3多变形,CSS3 clip-path polygon图形构建与动画变换二三事
- linux用户态和内核态堆栈,Linux内核态、用户态简介与IntelCPU特权级别--Ring0-3
- 0.96寸OLED屏幕
- 你想成为什么样的人取决于你付出了多少?
- 巴西龟饲养日志----冬眠记录
- crontab 奇数时间定时执行
- 如何理解IT、OT、CT?边缘计算
- 笔记本电脑设备管理器中'符合USBxHCI的主机控制器'出现感叹号,所有的USB接口失灵--解决
- IC功能芯片的封装和包装经验
- 【Java】2022年团体程序设计天梯赛 L1 和 L2-042 题解
热门文章
- python入门经典100例-Python3经典100例(Python3入门习题) 含答案 doc版
- python处理excel表格-如何用python处理excel表格
- 语音识别系统_智能语音识别系统_第三方语音识别系统 - 云+社区 - 腾讯云
- linux的课程完全看不懂,学习Linux命令神器-看不懂直接给你解释
- python windows 消息通讯_如何使用python與windows中的事件/消息掛鈎
- mysql排序规则英文 数字_如何在MySQL中为日语设置模式排序规则
- axios的http拦截
- 开发中git的常用命令
- 开源安卓播放器:Dolphin Player 简单分析
- svm 文本分类 matlab,livsvm文本分类总结详解