大致思路
预处理:key "value"
使得key的形式为:{{ key }} "value"的形式为:value
分别处理每一行
①查找所有可能出现的{{ key }},将其替换为一个特殊的不可打印标记字符,而不是对应的value。把value压入vector<string> val,而这个特殊的不可打印标记字符就是:char(val.size()-1),标记了value的编号。
原因:有点奇技淫巧的感觉,但是这样做有效的避免了递归处理(题目中说{{ key }}不会出现ASCII码小于32的字符)
②处理不合法的{{ key }},将其删除
(这个有点麻烦,废了点脑筋,但是如果不考虑这一点,也能够得到80分)
方法:查找每一对"{{ "和" }}",并考察其中间的内容,如果其中出现了除空格外的可打印字符,则一定是不合法的。
③将所有的标记字符替换为对应的value
感觉是乱搞把这题做出来了,不是特别严谨,细究的话应该还有BUG
C++满分代码(带注释)
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
int m,n;
string line[105]; //储存待处理的每一行
string key[105]; //{{ key }}
string value[105]; //key对应的value
string tmp,t1,t2;
vector<string> val; //储存每一行需要替换的value
void deal_line(string& str)
{
string temp;
val.clear();
size_t p;
for(int i=0; i<n; ++i)
{
while((p = str.find(key[i])) != string::npos) //处理存在的{{ key }}
{
val.push_back(value[i]);
tmp = char(val.size()-1); //不可打印标记字符,保证ASCII小于32
str.replace(p,key[i].length(),tmp);
}
}
size_t lefts = 0, rights = 0; // "{{ "和" }}"的位置
bool flag;
while(true)
{
lefts = str.find("{{ ", lefts);
rights = str.find(" }}", rights);
if(lefts != string::npos && rights != string::npos && lefts < rights) //考察"{{ "和" }}"中间的内容
{
flag = 0;
for(size_t i=lefts; i<rights; ++i)
if(str[i] != ' ' && str[i] > 32) //存在可打印字符
{
flag = 1;
break;
}
if(flag == 1) str.erase(str.begin()+lefts, str.begin()+rights+3); //删除它
}
else break;
}
for(int i=0; i<val.size(); ++i) //将标记字符替换回来
str.replace(str.find(char(i)),1,val[i]);
}
int main()
{
cin>>m>>n;
cin.get();
for(int i=0; i<m; ++i) //输入
getline(cin, line[i]);
for(int i=0; i<n; ++i) //处理 key "value"
{
getline(cin, tmp);
t1 = "{{ " + tmp.substr(0,tmp.find(" \"")) + " }}"; // t1是{{ key }}
t2 = tmp.substr(tmp.find("\"")); // t2是value
t2.erase(t2.begin());
t2.erase(t2.end()-1);
key[i] = t1;
value[i] = t2;
}
for(int i=0; i<m; ++i) //处理每一行
deal_line(line[i]);
for(int i=0; i<m; ++i) //输出
cout<<line[i]<<"\n";
return 0;
}