题解 | #配置文件恢复#
配置文件恢复
http://www.nowcoder.com/practice/ca6ac6ef9538419abf6f883f7d6f6ee5
题目的主要信息:
输入关键字,以“最短唯一匹配原则”匹配命令:
- 若只输入一字串,则只匹配一个关键字的命令行。
- 若只输入一字串,但本条命令有两个关键字,则匹配失败。
- 若输入两字串,则先匹配第一关键字,如果有匹配但不唯一,继续匹配第二关键字,如果仍不唯一,匹配失败。
- 若输入两字串,则先匹配第一关键字,如果有匹配但不唯一,继续匹配第二关键字,如果唯一,匹配成功。
- 若输入两字串,第一关键字匹配成功,则匹配第二关键字,若无匹配,失败。
- 若匹配失败,打印“unknown command”
方法一:
用cmdin储存所有可能的命令行,命令行分为两部分存储。首先将输入的字符串按照空格划分为s1和s2,如果该字符串有两个关键字则s2不为空。然后遍历一遍cmdin进行匹配,如果第一个关键字匹配成功,且第二个匹配成功或没有第二个关键字,则表示命令匹配成功。匹配命令用的find函数。用count1统计第一个关键字匹配成功的数量,count2统计第二个关键字匹配成功的数量。最后,如果两个关键字都匹配成功,且只有一组匹配即count1=count2=1,则匹配成功。 具体做法:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
vector<pair<string, string>> cmdin = { { "reset","" } ,{ "reset","board" } ,{ "board","add" } ,{ "board","delete" } ,{ "reboot","backplane" } ,{ "backplane","abort" } };
vector<string> cmdout = { "reset what" ,"board fault" ,"where to add" ,"no board at all" ,"impossible" ,"install first" };
string s;
while (getline(cin,s)){
string s1 , s2;
int pos = 0;
//以空格为分界划分
while (pos < s.size() && s[pos] != ' '){//遍历一遍找到空格的位置
pos++;
}
s1 = s.substr(0, pos);
if (pos != s.size()){
s2 = s.substr(pos + 1, s.size());
}
int count1 = 0, count2 = 0;
string result;
for (auto iter=cmdin.begin();iter!=cmdin.end();iter++){
int flag1 = iter->first.find(s1) == 0? 1 : 0;//判断第一个关键字是否匹配
int flag2;
if (s2 != "") {
flag2 = iter->second.find(s2) == 0? 1 : 0;//判断第二个关键字是否匹配
}else if(s2==""&&iter->second==""){//如果没有第二个关键字,默认匹配成功
flag2 = 1;
}else{
flag2 = 0;
}
if (flag1 && flag2)//两个关键字都匹配上了
{
count1++;
count2++;
result = cmdout[iter - cmdin.begin()];
}
}
if (count1 == 1 && count2 == 1){//两个关键字都匹配成功,且只有一组匹配
cout << result << endl;
}else {//匹配失败或有多组匹配
cout << "unknown command" << endl;
}
}
return 0;
}
复杂度分析:
- 时间复杂度:O(1),对于每一个输入的子串都只需要常数时间匹配和比较。
- 空间复杂度:O(1),只用了常数空间。
方法二:
正则表达式。整体思路和方法一相同,方法一匹配的方法是用find函数,方法二将匹配的方法改为正则表达式,正则表达式为关键字加上若干个小写字母拼接而成,两个关键字分别匹配,如果两个关键字都匹配成功,且只有一组配对,则整个命令匹配成功。
具体做法:
#include <iostream>
#include <string>
#include <regex>
#include <vector>
using namespace std;
int main(){
vector<pair<string, string>> cmdin = { { "reset","" } ,{ "reset","board" } ,{ "board","add" } ,{ "board","delete" } ,{ "reboot","backplane" } ,{ "backplane","abort" } };
vector<string> cmdout = { "reset what" ,"board fault" ,"where to add" ,"no board at all" ,"impossible" ,"install first" };
string s;
while (getline(cin,s)){
string s1 , s2;
int pos = 0;
//以空格为分界划分
while (pos < s.size() && s[pos] != ' '){//遍历一遍找到空格的位置
pos++;
}
s1 = s.substr(0, pos);
if (pos != s.size()){
s2 = s.substr(pos + 1, s.size());
}
int count1 = 0, count2 = 0;
string result;
for (auto iter=cmdin.begin();iter!=cmdin.end();iter++){
string pattern1 = s1 + "[a-z]*";//正则表达式
int flag1 = regex_match(iter->first, regex(pattern1));//第一个关键字匹配
string pattern2 = s2 + "[a-z]*";//正则表达式
int flag2 = 0;
if((s2 == "" && iter->second == "")){
flag2 = 1;
}else if(s2 != ""){
flag2 = regex_match(iter->second, regex(pattern2));//第二个关键字匹配
}
if (flag1 && flag2)//两个关键字都匹配上了
{
count1++;
count2++;
result = cmdout[iter - cmdin.begin()];
}
}
if (count1 == 1 && count2 == 1){//两个关键字都匹配成功,且只有一组匹配
cout << result << endl;
}else {//匹配失败或有多组匹配
cout << "unknown command" << endl;
}
}
return 0;
}
复杂度分析:
- 时间复杂度:O(1),对于每一个输入的子串都只需要常数时间匹配和比较。
- 空间复杂度:O(1),只用了常数空间。