替换字符后匹配
难度:
标签:
题目描述
代码结果
运行时间: 67 ms, 内存: 16.8 MB
/*
* 思路:
* 1. 使用 Java Stream 构建从 old 到 new 的映射表。
* 2. 生成所有可能的 sub 替换形式。
* 3. 过滤出在 s 中的子串。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public boolean canTransform(String s, String sub, char[][] mappings) {
// 构建映射表
Map<Character, List<Character>> map = Arrays.stream(mappings)
.collect(Collectors.groupingBy(m -> m[0],
Collectors.mapping(m -> m[1], Collectors.toList())));
// 生成所有可能的字符串
return generateAll(sub.toCharArray(), map, 0).stream()
.anyMatch(s::contains);
}
private List<String> generateAll(char[] sub, Map<Character, List<Character>> map, int index) {
if (index == sub.length) {
return Collections.singletonList(new String(sub));
}
List<String> results = new ArrayList<>();
char original = sub[index];
results.addAll(generateAll(sub, map, index + 1));
if (map.containsKey(original)) {
for (char replacement : map.get(original)) {
sub[index] = replacement;
results.addAll(generateAll(sub, map, index + 1));
sub[index] = original;
}
}
return results;
}
}
解释
方法:
该题解使用了位运算和位掩码的方法来检查是否可以通过替换使得子字符串 `sub` 匹配字符串 `s` 的某一部分。首先,使用两个大小为128的数组(因为ASCII字符的范围是0-127),`old` 和 `new` 来表示字符在字符串 `s` 中出现的位置。`new` 数组通过位移和按位或操作记录每个字符在 `s` 中的位置。然后,使用 `mappings` 更新 `old` 数组,使得如果字符 `c1` 可以被映射为 `c2`,则 `c1` 的位置信息也会包含 `c2` 的位置信息。最后,通过按位与操作检查 `sub` 是否为 `s` 的子字符串。如果 `sub` 中的每个字符都可以在 `s` 中找到对应位置,且这些位置是连续的,则返回 `true`。
时间复杂度:
O(n + m + k)
空间复杂度:
O(1)
代码细节讲解
🦆
题解中提到使用位运算记录字符在字符串中的位置,请问如何理解这种位运算的具体实现细节?
▷🦆
为什么题解选择使用大小为128的数组来记录字符位置,是否考虑过使用其他数据结构,比如哈希表?
▷🦆
在处理`mappings`的时候,更新`old`数组的操作`old[ord(c1)] |= new[ord(c2)]`是如何确保`sub`中的每个字符都可以被替换并匹配的?
▷