P1928 外星密码

题目链接:

本题如果直接模拟去做的话极为繁琐,输入的这个字符串是被多重「压缩」的,所以一重一重地「解压缩」可能会非常非常麻烦(不过应该是可行的),导致代码极其难以理解。

所以,我们使用递归算法,在读入这个字符串之后,找出被压缩的内容,再对被压缩的那个字符串实行「解压缩」操作。

举个例子:AC[3FUN]

首先,我们找到了被压缩的字符串:3FUN

对3FUN进行解压,得到FUNFUNFUN

再把原来的字符串AC后面添上FUNFUNFUN即可。

由于这个只有一重「压缩」,可能递归思想体现的不太明显,这里再举一个多重「压缩」的例子:

SAD[4MLE[2TLE[2RE[2WA]]]

首先找到被「压缩」的部分:

[2MLE[2TLE[2RE[2WA]]]]

(从此处开始剩下的部分就是递归的内容了,全部由程序自主实现)

对这个部分进行解压,找到被「压缩」的部分:

[2TLE[2RE[2WA]]]

再对这个部分进行解压,找到被「压缩」的部分:

[2RE[2WA]]

再对这个部分进行解压,找到被「压缩」的部分:

[2WA]

(开始一层一层跳出递归)

对这个部分进行解压并加到前一个字符串的末尾:

[2REWAWA]

再对这个部分进行解压并加到前一个字符串的末尾:[2TLEREWAWAREWAWA]

再对这个部分进行解压并加到前一个字符串的末尾:

[2MLETLEREWAWAREWAWATLEREWAWAREWAWA]

再对这个部分进行解压并加到前一个字符串的末尾:

SADMLETLEREWAWAREWAWATLEREWAWAREWAWAMLETLEREWAWAREWAWATLEREWAWAREWAWA

至此,递归结束,「密码」破译完毕。

所以,我们只需要找到被「压缩」的子串,并把这个字符串扔给「解压缩」程序即可。

最重要的是: 千万不要跳进这个函数里面企图探究更多细节,否则就会陷入无穷的细节无法自拔。——OI Wiki

我们也看到了,上面对SAD[4MLE[2TLE[2RE[2WA]]]的分析细节很多很多,十分复杂。

我们只需要把这个需要「解压缩」的字串扔给「解压缩」函数即可。

#include <bits/stdc++.h>

using namespace std;

string solve() {
	char c;
	string s, p;
	while (cin >> c) {//这里如果修改成while ((c = getchar()) != '\n') 则会有一个测试点MLE
		if (c == '[') {
			int n;
			cin >> n;
			p = solve();
			while (n--) s += p;
		}
		else if (c == ']') return s;
		else s += c;//没有被压缩就直接在最后添上这个字符
	}
	return s;
}

int main()
{
	cout << solve();
	return 0;
}

还应注意的是,由于压缩次数 \(k \in 1 \sim 99\) 可能为两位数,我们在读入字符串的时候考虑字符逐个读入。如果读到'['就单独设置一个整数来读取,然后递归处理子串。如果读到']'就说明找到了压缩子串的末尾,结束这一层递归并返回解压后的子串。
参考资料:

posted @ 2024-02-03 17:51  胖柚の工作室  阅读(70)  评论(0)    收藏  举报