魔王语言解释
问题描述
有一个魔王总是使用自己的一种非常精练而抽象的语言讲话,没有人能听得懂,但他的语言是可以逐步解释成人能听懂的语言,因为他的语言是由以下两种形式的规则由人的语言逐步抽象上去的:
在这两种形式中,从左到右均表示解释。试写一个魔王语言的解释系统,把他的话解释成人能听得懂的话。
基本要求
用下述两条具体规则和上述规则形式(2)实现。设大写字母表示魔王语言的词汇;小写字母表示人的语言词汇,希腊字母表示可以用大写字母或小写字母代换的变量。魔王语言可含人的词汇。
测试数据
B(ehnxgz)B
解释成tsaedsaeezegexenehetsaedsae
。
若将小写字母与汉字建立下表所示的对应关系,则魔王说的话是:“天上一只鹅地上只鹅鹅追鹅赶鹅下鹅蛋鹅恨鹅天上一只鹅地上一只鹅”。
实现提示
将魔王的语言自右至左进栈,总是处理栈顶字符。若是开括号,则逐一出栈,将字母顺序入队列,直至闭括号出栈,并按规则要求逐一出队列再处理后入。其他情形较简单,请读者思考应如何处理。应首先实现栈和队列的基本操作。
选作内容
- 由于问题的特殊性,可以实现栈和队列的顺序存储空间共享。
- 代换变量的数目不限,则在程序开始运行时首先读入一组第一种形式的规则,而不是把规则固定在程序中(第二种形式的规则只能固定在程序中)。
思路
首先定义一些常量和类型别名,包括状态 Status
和元素类型 ElemType
。接着,定义了几个字符串常量 A_NEW
和 B_NEW
,分别用于替换字符 ‘A’ 和 ‘B’。
然后定义了四个函数 fa
, fb
, fc
和 fd
,这四个函数按照特定规则转换输入的字符串。fa
和 fb
函数用于将字符串中的 ‘B’ 和 ‘A’ 分别替换为 B_NEW
和 A_NEW
。
fc
函数用于处理字符串中的括号。对于每个开括号,找到对应的闭括号,并将其中的字符压入栈中,然后将栈中的字符依次弹出并添加到新的字符串中。
fd
函数将字符串中的每个字符映射到对应的汉字。
最后,在 main
函数中,读取输入的字符串,然后按照 fa
, fb
, fc
, fd
的顺序对字符串进行处理,最后输出处理后的字符串。
算法分析
时间复杂度是 O ( n ) O(n) O(n),其中 n n n 是字符串的长度,空间复杂度是 O ( m ) O(m) O(m),其中 m m m 是括号中字符的数量。
AC代码
#include <algorithm>
#include <iostream>
#include <stack>
#define AUTHOR "HEX9CF"
using namespace std;
using Status = int;
using ElemType = int;
const int N = 1e6 + 7;
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int INFEASIBLE = -1;
// const int OVERFLOW = -2;
const string A_NEW = "sae";
const string B_NEW = "tAdA";
string fa(string str) {
int pos = 0;
while ((pos = str.find('B', pos)) != string::npos) {
str.replace(pos, 1, B_NEW);
pos += B_NEW.length();
}
return str;
}
string fb(string str) {
int pos = 0;
while ((pos = str.find('A', pos)) != string::npos) {
str.replace(pos, 1, A_NEW);
pos += A_NEW.length();
}
return str;
}
string fc(string str) {
for (int i = 0; i < str.length(); i++) {
if (str[i] == '(') {
string s = "";
stack<char> stk;
int begin = i;
char xita = str[++i];
while (str[++i] != ')') {
stk.push(str[i]);
// cout << str[i] << endl;
}
int len = stk.size();
while (stk.size()) {
char t = stk.top();
stk.pop();
s += xita;
s += t;
}
s += xita;
// cout << s << endl;
str.replace(begin, len + 3, s);
i = begin + len * 2 + 1;
}
}
return str;
}
string fd(string str) {
string ret = "";
for (const auto i : str) {
switch (i) {
case 't':
ret += "天";
break;
case 'd':
ret += "地";
break;
case 's':
ret += "上";
break;
case 'a':
ret += "一只";
break;
case 'e':
ret += "鹅";
break;
case 'z':
ret += "追";
break;
case 'g':
ret += "赶";
break;
case 'x':
ret += "下";
break;
case 'n':
ret += "蛋";
break;
case 'h':
ret += "恨";
break;
}
}
return ret;
}
int main() {
string str;
cin >> str;
str = fa(str);
str = fb(str);
str = fc(str);
str = fd(str);
cout << str << endl;
return 0;
}