题目描述
给你一个字符串 s
,它包含一些括号对,每个括号中包含一个 非空 的键。
- 比方说,字符串
"(name)is(age)yearsold"
中,有 两个 括号对,分别包含键"name"
和"age"
。
你知道许多键对应的值,这些关系由二维字符串数组 knowledge
表示,其中 knowledge[i] = [key_i, value_i]
,表示键 key_i
对应的值为 value_i
。
你需要替换 所有 的括号对。当你替换一个括号对,且它包含的键为 key_i
时,你需要:
- 将
key_i
和括号用对应的值value_i
替换。 - 如果从
knowledge
中无法得知某个键对应的值,你需要将key_i
和括号用问号"?"
替换(不需要引号)。
knowledge
中每个键最多只会出现一次。s
中不会有嵌套的括号。
请你返回替换 所有 括号对后的结果字符串。
样例
输入:s = "(name)is(age)yearsold", knowledge = [["name","bob"],["age","two"]]
输出:"bobistwoyearsold"
解释:
键 "name" 对应的值为 "bob",所以将 "(name)" 替换为 "bob"。
键 "age" 对应的值为 "two",所以将 "(age)" 替换为 "two"。
输入:s = "hi(name)", knowledge = [["a","b"]]
输出:"hi?"
解释:由于不知道键 "name" 对应的值,所以用 "?" 替换 "(name)"。
输入:s = "(a)(a)(a)aaa", knowledge = [["a","yes"]]
输出:"yesyesyesaaa"
解释:相同的键在 s 中可能会出现多次。
键 "a" 对应的值为 "yes" ,所以将所有的 "(a)" 替换为 "yes"。
注意,不在括号里的 "a" 不需要被替换。
输入:s = "(a)(b)", knowledge = [["a","b"],["b","a"]]
输出:"ba"
限制
1 <= s.length <= 10^5
0 <= knowledge.length <= 10^5
knowledge[i].length == 2
1 <= key_i.length, value_i.length <= 10
s
只包含小写英文字母和圆括号'('
和')'
。s
中每一个左圆括号'('
都有对应的右圆括号')'
。s
中每对括号内的键都不会为空。s
中不会有嵌套括号对。key_i
和value_i
只包含小写英文字母。knowledge
中的key_i
不会重复。
算法
(哈希表) $O(n + mL)$
- 首先将所有替换关系存储哈希表。
- 然后遍历字符串,根据哈希表替换每个括号内的内容。
时间复杂度
- 初始化哈希表需要 $O(mL)$ 的时间,其中 $m$ 为
key
的数量,$L$ 为key
和value
的最大长度。 - 遍历字符串时,每个位置最多被遍历两次,且 总的查询时间 最多为 $O(n)$。
- 故总时间复杂度为 $O(n + mL)$。
空间复杂度
- 需要 $O(mL)$ 的额外空间存储哈希表。
C++ 代码
class Solution {
public:
string evaluate(string s, vector<vector<string>>& knowledge) {
unordered_map<string, string> mp;
for (const auto &k : knowledge)
mp[k[0]] = k[1];
const int n = s.size();
string ans;
for (int i = 0, last = -1; i < n; i++) {
if (s[i] == '(') {
last = i + 1;
} else if (s[i] == ')') {
string t = s.substr(last, i - last);
if (mp.find(t) == mp.end()) ans += '?';
else ans += mp[t];
last = -1;
} else {
if (last == -1) ans += s[i];
}
}
return ans;
}
};