万万没想到之聪明的编辑(有穷自动机做法)
突发奇想,这学期刚学编译原理,于是用有穷自动机做了一下,简洁高效。自动机如下图,其中:
- “同”代表当前读到字符与上一字符相同;
- “不同”代表当前读到字符与上一字符不同,作为转换边的条件。因此要从下标1开始读。
自动机初始化:将输入字符串的第一个字符添加到结果字符串并且直接进入状态1。
状态转换图有了,接下来就是在适当的地方插入字符构造修正字符串了,这个很容易想,见函数 repairTransfer
中 output.append
出现的位置即可理解,就是一个个字符的插入result字符串就可以啦:
#include <iostream>
#include <string>
using namespace std;
int stateTransfer(bool same, int current_state, int i, string& input, string& output) {
if (current_state == 1) {
output.append(1, input[i]);
if (same) return 2;
else return 1;
}
else if (current_state == 2) {
if (same) {
return 2;
}
else {
output.append(1, input[i]);
return 3;
}
}
else if (current_state == 3) {
if (same) {
return 3;
}
else {
output.append(1, input[i]);
return 1;
}
}
}
string repair(string s) {
string result;
int slen = s.length();
if (slen == 0) return result;
result.append(1, s[0]);//进入状态1
int state = 1;
for (int i = 1; i < slen; ++i) {
state = stateTransfer((s[i] == s[i - 1]), state, i, s, result);
}
return result;
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
string str;
cin >> str;
cout << repair(str) << endl;
}
return 0;
}