首页 > 其他分享 >[JSOI2007] 字串加密

[JSOI2007] 字串加密

时间:2022-08-17 15:12:02浏览次数:92  
标签:字符 加密 int text tp 字串 JSOI2007 sa

题链:luogu

JS同学?

Description

让JS同学对环形字符串进行重组加密。加密规则是:

列出 \(n\) 个字符串并字典序升序,一次取末尾字符作为加密后的长度为 \(n\) 的密码串。

Analysis

看到字典序升序共 \(n\) 个字串等关键词,你不由地想到了后缀数组(\(\text{Suffix Array}\),\(\text{SA}\))算法。

回忆你曾经学过的 \(\text{SA}\) 算法,感到十分生疏,只记得 \(sa_i\) 是表示原序列第 \(sa_i\) 个字符开始的后缀字串在字典序升序后的 \(\text{rank}\) 为 \(i\),你束手无措,但转而想到貌似只需要会求 \(sa_i\) 即可。

先不考虑环形,题目中让我们求最后一个字符,你想到 \(sa_i\) 求的是第一个字符位置,貌似有所联系;考虑环形,最后一个字符的后一个字符就是第一个字符,故只需知道第一个字符的位置,\(-1\) 即为最后字符的位置(注意循环,勿越界)。

但是通常 \(\text{SA}\) 只考虑非环情况,若要考虑,常见做法是 \(2\times n\),于是你决定 s[i+n] = s[i]。可惜的是这样你在最后会发现有 \(2\times n\) 个 \(sa_i\),你不知道该选哪一个输出。

回归 \(sa_i\) 的定义,得知为 开头字符在原序列中的位置,故只有 \(sa_i\) 不超过 \(n\) 时,你才需要输出答案 \(s_{sa_i-1}\)。

看样例,得知 \(sa_1\) 为 \(11>6\),舍弃;\(sa_2\) 为 \(5<6\),可用,故首个输出字符为 \(s_{5-1}=s_4=\text{I}\);后面以此类推。

Code

#include <stdio.h>
#include <string.h>
#include <iostream>
const int N = (int)1e6 + 5;
char s[N << 1]; int n, m, sa[N], rk[N], tp[N], tax[N];
inline void Rsort() { //基数排序
	for (int i = 1; i <= m; ++i) tax[i] = 0;
	for (int i = 1; i <= n; ++i) ++tax[rk[i]];
	for (int i = 1; i <= m; ++i) tax[i] += tax[i - 1];
	for (int i = n; i >= 1; --i) sa[tax[rk[tp[i]]]--] = tp[i];
}
inline void Csort() { //getSA
	for (int i = 1; i <= n; ++i) rk[i] = s[i], tp[i] = i;
	Rsort();
	for (int w = 1, temp; temp < n && w <= n; m = temp, w <<= 1) {
		temp = 0; for (int i = n - w + 1; i <= n; ++i) tp[++temp] = i;
		for (int i = 1; i <= n; ++i)
			if (sa[i] > w) tp[++temp] = sa[i] - w;
		Rsort(); std:: swap(rk, tp); rk[sa[1]] = temp = 1;
		for (int i = 2; i <= n; ++i)
			rk[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? temp : ++temp;
	}
}
int main(void) {
	freopen("cipher.in", "r", stdin); freopen("cipher.out", "w", stdout);
	scanf("%s", s + 1);
	n = strlen(s + 1); m = (1 << 7) - 1;
	for (int i = 1; i <= n; ++i) s[n + i] = s[i]; n <<= 1;
	Csort();
	for (int i = 1; i <= n; ++i)
		if (sa[i] <= n / 2) putchar(s[(sa[i] - 1 + n - 1) % n + 1]); putchar('\n'); //找答案
	return 0;
}

The end. Thanks.

(走过路过,一定赞过qwq

标签:字符,加密,int,text,tp,字串,JSOI2007,sa
From: https://www.cnblogs.com/dry-ice/p/JSOI2007-d2t3.html

相关文章

  • kafka加密后命令行操作kafka
    kafka加密后命令行操作kafkakafka安装时使用加密安装时,命令行操作kakfa进行topic创建,偏移量查看,消费者消费状况查询都需要使用到改密码,此处作为记录,便于后续查询使用......
  • PHP加密JS解密【转】
    转载地址:https://www.fengjinwei.com/blog-1139759.htmlPHP加密:functionstrencode2($string){$string=base64_encode($string);$key='123456';......
  • PHP与JS互相加密解密方法2.0【转载】
    本文转自:https://blog.csdn.net/qq_32845825/article/details/123705487前言:之前写过一个加密解密1.0版本的,但是随着PHP版本升级,那个不能用了,当初使用的是PHP5中的mcrypt......
  • SHA256加密算法
    https://www.cnblogs.com/zhangwuxuan/p/12863273.html算法介绍:比特币挖矿的御用算法SHA256是SHA-2下细分出的一种算法SHA-2,名称来自于安全散列算法2(英语:SecureHashA......
  • 非对称加密与对称加密的区别
    在了解对称加密和非对称加密的区别之前我们先了解一下它们的定义:对称加密(SymmetricCryptography),又称私钥加密对称加密是最快速、最简单的一种加密方式,加密(encryption)与......
  • Abp加密模块
    ABP加密模块最近项目中用到了加密,且甲方要求必须要求国标加密。项目使用的是ABP开发,所以写了此模块(可以单独使用,也可以加密数据库字段)。这里引用一个博主的文章内容引......
  • https数据传输流程 加密
    客户端先从服务器获取到证书,证书中包含公钥客户端将证书进行校验客户端生成一个对称密钥,用证书中的公钥进行加密,发送给服务器服务器得到这个请求后用私钥进行解密,得到......
  • RS256 - java具体使用 非对称加密算法 - 总结心得
    1.背景有个需求需要在java使用非对称加密RS256算法,网上博客都翻篇了,基本都是赋值粘贴,没有个是可用的,80%都是粘贴了一篇c#语言写的代码,什么风气?以前的博客氛围哪里......