题意: 在START 和END 之间给出一个替换列表,每行有两个单词a和b。之后又在START 和END 给出几句话,要求把每句话中,在替换列表出现过的b,都替换成a。
题解: 一个字符串替换成另一个字符串,用map来做是最简单的。同时为了复习字典树,也用字典树做了一遍。
过程中犯的错:
- 每句话中取单词。后续代码中呈现的是我能想到的最简便的方法,一开始为了这个弄得非常复杂。
- 字典树中的search 函数。我特意改成了返回string类型,方便我直接输出。但是有一种情况,比如我替换列表中出现了单词abcde,当我搜寻单词abcd 的替换结果的时候,如果列表中没有这个单词,是应该返回原单词不替换的。但因为字典树的构造特性,虽然替换列表中不出现abcd,但出现过abcde,所以树中存在abcd,需要注意。
map
#include<bits/stdc++.h>
using namespace std;
string t, s;
char str[3005];
map<string, string> m;
int main(){
cin >> t;
while(cin >> t && t != "END"){
cin >> s;
m[s] = t;
}
cin >> t;getchar();
while(gets(str)){
if(strcmp(str, "END") == 0) break;
s = "";
int len = strlen(str);
for(int i = 0; i < len; i++){
if(str[i] < 'a' || str[i] > 'z'){
if(m[s] != "") cout << m[s] << str[i];
else cout << s << str[i];
s = "";
}
else s += str[i];
}
cout << endl;
}
return 0;
}
字典树
#include<bits/stdc++.h>
using namespace std;
string t, s;
char str[3005];
struct trie{
string s;
trie* next[26];
trie(){
for(int i = 0; i < 26; i++) next[i] = NULL;
s = "";
}
};
trie root;
void insert(string str, string s){
trie *p = &root;
for(int i = 0; str[i]; i++){
if(p->next[str[i] - 'a'] == NULL)
p->next[str[i] - 'a'] = new trie;
p = p->next[str[i] - 'a'];
}
p->s = s;
}
string search(string str){
trie *p = &root; int i = 0;
while(str[i]){
int n = str[i++] - 'a';
if(p->next[n] == NULL) return str;
p = p->next[n];
}
if(p->s.length()== 0) return str;
return p->s;
}
int main(){
cin >> t;
while(cin >> t && t != "END"){
cin >> s;
insert(s, t);
}
cin >> t;getchar();
while(gets(str)){
if(strcmp(str, "END") == 0) break;
s = "";
int len = strlen(str);
for(int i = 0; i < len; i++){
if(str[i] < 'a' || str[i] > 'z'){
cout << search(s) << str[i];
s = "";
}
else s += str[i];
}
cout << endl;
}
return 0;
}