
题目描述
给定一个 replacements
映射和一个可能包含格式为 %var%
占位符 的字符串 text
,其中每个 var
对应 replacements
中的一个键。每个替换值本身可能包含 一个或多个 此类占位符。每个 占位符 都被与其相应的替换键对应的值替换。
返回完全替换后 不 含任何 占位符 的 text
字符串。
示例 1:
输入:replacements = [["A","abc"],["B","def"]], text = "%A%_%B%"
输出:"abc_def"
解释:
- 映射将
"A"
与 "abc"
关联,并将 "B"
与 "def"
关联。
- 用
"abc"
替换文本中的 %A%
,并用 "def"
替换文本中的 %B%
。
- 最终文本变为
"abc_def"
。
示例 2:
输入:replacements = [["A","bce"],["B","ace"],["C","abc%B%"]], text = "%A%_%B%_%C%"
输出:"bce_ace_abcace"
解释:
- 映射将
"A"
与 "bce"
关联,"B"
与 "ace"
关联,以及 "C"
与 "abc%B%"
关联。
- 用
"bce"
替换文本中的 %A%
,并用 "ace"
替换文本中的 %B%
。
- 接着,对于
%C%
,用 "ace"
替换 "abc%B%"
中的 %B%
来得到 "abcace"
。
- 最终文本变为
"bce_ace_abcace"
。
提示:
1 <= replacements.length <= 10
replacements
中的每个元素是一个双值列表 [key, value]
,其中:
key
是一个大写英语字母。
value
是一个最多有 8 个字符,可能包含 0 个或更多格式为 %<key>%
的占位符的非空字符串。
- 所有的替换键互不相同。
text
字符串是通过从替换映射中随机串联所有 key 占位符(格式为 %<key>%
)而形成的,以虚线分隔。
text.length == 4 * replacements.length - 1
text
或任何替换值中的每个占位符对应 replacements
映射中的一个键。
- 替换键之间没有循环依赖。
解法
方法一:哈希表 + 递归
我们用一个哈希表 \(\textit{d}\) 来存储替换的映射关系,然后定义一个函数 \(\textit{dfs}\) 来递归地替换字符串中的占位符。
函数 \(\textit{dfs}\) 的执行逻辑如下:
- 在字符串 \(\textit{s}\) 中查找第一个占位符的起始位置 \(i\),如果找不到,则返回 \(\textit{s}\);
- 在字符串 \(\textit{s}\) 中查找第一个占位符的结束位置 \(j\),如果找不到,则返回 \(\textit{s}\);
- 截取占位符的键值 \(key\),然后递归地替换占位符的值 \(d[key]\);
- 返回替换后的字符串。
在主函数中,我们调用 \(\textit{dfs}\) 函数,传入文本字符串 \(\textit{text}\),并返回结果。
时间复杂度 \(O(m + n \times L)\),空间复杂度 \(O(m + n \times L)\)。其中 \(m\) 为替换映射的长度,而 \(n\) 和 \(L\) 分别为文本字符串的长度和占位符的平均长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def applySubstitutions(self, replacements: List[List[str]], text: str) -> str:
def dfs(s: str) -> str:
i = s.find("%")
if i == -1:
return s
j = s.find("%", i + 1)
if j == -1:
return s
key = s[i + 1 : j]
replacement = dfs(d[key])
return s[:i] + replacement + dfs(s[j + 1 :])
d = {s: t for s, t in replacements}
return dfs(text)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | class Solution {
private final Map<String, String> d = new HashMap<>();
public String applySubstitutions(List<List<String>> replacements, String text) {
for (List<String> e : replacements) {
d.put(e.get(0), e.get(1));
}
return dfs(text);
}
private String dfs(String s) {
int i = s.indexOf("%");
if (i == -1) {
return s;
}
int j = s.indexOf("%", i + 1);
if (j == -1) {
return s;
}
String key = s.substring(i + 1, j);
String replacement = dfs(d.getOrDefault(key, ""));
return s.substring(0, i) + replacement + dfs(s.substring(j + 1));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | class Solution {
public:
string applySubstitutions(vector<vector<string>>& replacements, string text) {
unordered_map<string, string> d;
for (const auto& e : replacements) {
d[e[0]] = e[1];
}
auto dfs = [&](this auto&& dfs, const string& s) -> string {
size_t i = s.find('%');
if (i == string::npos) {
return s;
}
size_t j = s.find('%', i + 1);
if (j == string::npos) {
return s;
}
string key = s.substr(i + 1, j - i - 1);
string replacement = dfs(d[key]);
return s.substr(0, i) + replacement + dfs(s.substr(j + 1));
};
return dfs(text);
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | func applySubstitutions(replacements [][]string, text string) string {
d := make(map[string]string)
for _, e := range replacements {
d[e[0]] = e[1]
}
var dfs func(string) string
dfs = func(s string) string {
i := strings.Index(s, "%")
if i == -1 {
return s
}
j := strings.Index(s[i+1:], "%")
if j == -1 {
return s
}
j += i + 1
key := s[i+1 : j]
replacement := dfs(d[key])
return s[:i] + replacement + dfs(s[j+1:])
}
return dfs(text)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | function applySubstitutions(replacements: string[][], text: string): string {
const d: Record<string, string> = {};
for (const [key, value] of replacements) {
d[key] = value;
}
const dfs = (s: string): string => {
const i = s.indexOf('%');
if (i === -1) {
return s;
}
const j = s.indexOf('%', i + 1);
if (j === -1) {
return s;
}
const key = s.slice(i + 1, j);
const replacement = dfs(d[key] ?? '');
return s.slice(0, i) + replacement + dfs(s.slice(j + 1));
};
return dfs(text);
}
|