1、题目描述
2、解题思路
如果字符串 pattern 和字符串 str 是遵循相同的规律,那么,pattern 的每一个字符一定对应 str 的某一个子串,而且是唯一对应。
例如:pattern = “abab”, str = “redblueredblue”
a -> read
b -> blue
因此,本题的目的就是找到这个对应关系,如果不存在对应关系,则不遵循相同的规律。
定义一个全局 HashMap<Character, String> 来存储映射关系,key 为 pattern 的字符,value 为 str 的子串。
一开始,map 中没有任何映射关系。
把 pattern = “abab” 的第一个字符 ‘a’ 和 str = “redblueredblue” 的第一个字符 “r” 当成映射关系,put 到 map 中。现在 map 中有一个映射关系 (‘a’, “r”)。
现在,问题变成查找 “bab” 和 “edblueredblue” 的映射关系,其中,‘a’ 必须映射 “r”。
很明显,这是一个回溯问题。
如果回溯到最后 pattern 没有字符了,且 str 也没有字符了,说明刚好映射完毕,返回 true。
如果 pattern 字符用完了,str 还有剩下的字符,说明有可能一开始的映射关系就是不对的,因此重新调整初始的映射关系,例如调整为 ‘a’ -> “re” ,继续回溯 “bab” 和 “dblueredblue”。
因为 “abab” 一个字符至少对应 "redblueredblue 的一个字符,“abab” 长度为 4,因此,‘a’ 最多对应 “redblueredb”,留三个字符给 “aba”。
我们遍历回溯以下情况:
以 (‘a’ -> “r”) 开始,查找 “bab” 和 “edblueredblue” 的映射关系;
以 (‘a’ -> “re”) 开始,查找 “bab” 和 “dblueredblue” 的映射关系
以 (‘a’ -> “red”) 开始,查找 “bab” 和 “blueredblue” 的映射关系
… … … …
以 (‘a’ -> “redblueredb”) 开始,查找 “bab” 和 “lue” 的映射关系
有可能中间某一个就直接返回 true,但是如果遍历完所有可能的开始,都没有返回 ture,说明也两个字符串不遵循相同的规律。
3、解题代码
class Solution {
Map<Character, String> map = new HashMap<>();
public boolean wordPatternMatch(String pattern, String str) {
//边界条件,如果pattern读完了,字符串也正好读完就true,如果字符串没读完就false
if (pattern.length() == 0) {
return str.length() == 0;
}
char letter = pattern.charAt(0);
//从1位开始尝试是否有映射,由于每个pattern至少得对应一个字符,所以如果字符串剩下的字符少于pattern剩下的字符数就可以停止循环了
for (int i = 1; i <= str.length() - pattern.length() + 1; i++) {
//mapStr是letter的映射,有则返回映射,没有则等于null
String substr = str.substring(0, i);
String mapStr = map.get(letter);
//这个pattern有映射,并且等于这段字符;
// 或者这段字符不是pattern的映射并且没有其他映射,就可以假设这个映射成立并继续尝试匹配剩下的字符
if ((mapStr != null && substr.equals(mapStr)) || (mapStr == null && !map.containsValue(substr))) {
//不管是否是正确答案,先放进map里面尝试
map.put(letter, substr);
//如果正好对了就返回true
if (wordPatternMatch(pattern.substring(1), str.substring(i))) {
return true;
} else if (mapStr == null) {
map.remove(letter);
}
}
}
//循环跑完都没有结果当然就返回false啦
return false;
}
}