想了好久,但运行TLE
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
typedef pair<string, string> PSS;
vector<PSS> dmap, result;
void find(PSS &p) {
string s = p.first;
int len = s.length(); // 获取新饮料名称的长度
int mo = dmap.size(); // 获取已知饮料等级的数量
bool flag=false;
// 查找匹配的字符串
for (int i = 0, j = 0; i < len; ++i) {
string target = dmap[j].first; // 获取当前已知等级的名称
int target_len = target.size(); // 获取当前已知等级的名称的长度
if (s[i] == target[i]) {
// 如果当前字符匹配成功,继续检查下一个字符
if (i == target_len - 1) {
// 如果已经匹配到当前已知等级的末尾,则将新饮料的等级设为当前已知等级的等级
p.second += dmap[j].second;
flag=true;
}
} else {
// 如果当前字符匹配失败,则尝试下一个已知等级
j = (j + 1) % mo;
// 重置i,因为当前字符未匹配成功,需要重新匹配
if(!flag) i = -1; // 循环结束后会自增1
}
}
// 如果无法匹配任何已知等级,则设置新饮料的等级为 "D"
if (p.second.empty()) p.second = "D";
}
int main() {
int n, m;
cin >> n >> m;
dmap.reserve(n); // 提前分配内存以避免多次重新分配
for (int i = 0; i < n; i++) {
string s, s1;
cin >> s >> s1;
dmap.push_back({s, s1});
}
sort(dmap.begin(), dmap.end()); // 根据第一个元素排序
for (int i = 0; i < m; i++) {
string s;
cin >> s;
result.push_back({s, ""});
}
for (auto& p : result) {
find(p);
cout << p.second << endl;
}
return 0;
}
用unordered_map
map内部使用红黑树(一种自平衡二叉查找树)来实现,而unordered_map则使用哈希表来实现
#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>
using namespace std;
unordered_map<string, string> dmap; // 使用哈希表存储已知的饮料名称和等级
vector<string> result;
void find(const string& s) {
auto it = dmap.find(s);
if (it != dmap.end()) {
// 如果找到匹配项,直接添加等级到结果中
result.push_back(it->second);
return;
}
// 遍历所有已知等级的饮料名称,检查每个已知等级的饮料名称是否是新饮料名字的前缀
for (const auto& entry : dmap) {
const string& known_drink = entry.first;
const string& level = entry.second;
if (s.substr(0, known_drink.length()) == known_drink) {
// 如果已知等级的饮料名称是新饮料名字的前缀,尝试将新饮料名字去除掉已知等级的饮料名称部分
string remainder = s.substr(known_drink.length());
// 查找剩下的部分是否在已知等级中
auto it_remainder = dmap.find(remainder);
if (it_remainder != dmap.end()) {
// 如果剩下的部分也在已知等级中,组合已知等级的等级作为新饮料的等级
result.push_back(level + it_remainder->second);
return;
}
}
}
// 如果无法拆解成已知等级的组合,则将其定为 "D" 级
result.push_back("D");
}
int main() {
int n, m;
cin >> n >> m;
// 读取已知的饮料名称和等级,存储到哈希表中
for (int i = 0; i < n; i++) {
string s, s1;
cin >> s >> s1;
dmap[s] = s1;
}
// 读取需要定级的饮料名称
for (int i = 0; i < m; i++) {
string s;
cin >> s;
find(s); // 查找并添加等级到结果中
}
// 输出结果
for (const auto& level : result) {
cout << level << endl;
}
return 0;
}
在CSDN看到的思路
我直接map存字符串和它对应的等级,然后读进来一个要判断的字符串,进行check,具体的check是去枚举分割点,把这个字符串分成两个,然后判断一下两个子串是不是出现过,如果都出现过,就记录一下(成功方案数cnt+1,且用res字符串把两个子串对应的等级拼起来),接着枚举,因为可能有不止一种枚举方案,最后枚举完,判断一下枚举方案是不是只有一种,如果cnt == 1就返回res,cnt > 1或者cnt == 0就返回‘D’
呜呜呜,别人写的精巧简洁,我写的又慢又臭又长
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
int n,m;
map<string,string> mp;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
string a,b;
cin>>a>>b;
mp[a]=b;
}
while(m--)
{
string s;
cin>>s;
//首先判断没有拼接的
if(mp.count(s)) cout<<mp[s]<<endl;// 返回键值等于key的元素的个数
//我原本以为,要一个一个字符来比较,这样效率太低了,而且我觉得s放在外面,因为我想着,mp遍历一次,找不完拼接的情况
//我原来不知道mp有自带的操作count,可以找整个容器键值等于key的元素,并返回个数,这样s是固定的,for外层循环就是mp元素
//考虑直接没有找到的情况,就是单次拼接、多次拼接、找不到
else{
int res=0;
string tmp;
for(auto it:mp)//遍历mp
{
int len=it.first.size();
if(len<=s.size())//等号可以去掉
{
if(s.substr(0,len)==it.first)
{
if(mp.count(s.substr(len,s.size())))
{
res++;
tmp=it.second+mp[s.substr(len,s.size())];
}
}
}
}
//res=0和res>1的情况
if(res!=1) cout<<"D"<<endl;
//res=1的情况
else cout<<tmp<<endl;
}
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>//自己敲的时候忘加了
using namespace std;
map <string,string> mp;
int n,m;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++)
{
string s,s1;
cin>>s>>s1;
mp[s]=s1;
}
while(m--)
{
string s;
cin>>s;
if(mp.count(s))cout<<mp[s]<<endl;
else{
string temp;
int res=0;
for(auto it:mp){
int len=it.first.length();
if(s.length()>len)
{
if(s.substr(0,len)==it.first){
if(mp.count(s.substr(len))){
res++;
temp+=it.second+mp[s.substr(len)];
}
}
}
}
if(res!=1)cout<<"D"<<endl;//第一次敲的时候把它们放外面了
else cout<<temp<<endl;
}
}
return 0;
}