题目来源
题目描述
class Solution {
public:
bool wordPatternMatch(string pattern, string str){
}
};
题目解析
题目意思
- 如果pattern和字符串str遵循相同的规律,那么pattern的每一个字符一定对应str的某一个子串,而且是唯一确定的
- 例如:pattern = “abab”, str = “redblueredblue”
- a -> read
- b -> blue
- 本题的目的就是找到这个对应关系,如果不存在这样的对应关系,则不遵循相同的规律
题目解析
- 这道题是290. 单词规律的扩展,区别在于290题之间的词已经用空格隔开了,这样可以一个单词一个单词的读入,然后来判断是否符合给定的特征
- 而这道题没有空格了,所以我们需要自己去分块。问题是怎么切分呢?
思路
- 定义一个全局的map<char, 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,说明也两个字符串不遵循相同的规律。
class Solution {
std::map<char, std::string> map;
public:
bool wordPatternMatch(string pattern, string str){
//边界条件,如果pattern读完了,字符串也正好读完就true,如果字符串没读完就false
if(pattern.empty()){
return str.empty();
}
char letter = pattern[0];
//从1位开始尝试是否有映射,由于每个pattern至少得对应一个字符,所以如果字符串剩下的字符少于pattern剩下的字符数就可以停止循环了
for (int i = 1; i <= str.size() - pattern.size() + 1; ++i) {
mapStr是letter的映射,有则返回映射,没有则等于null
std::string substr = str.substr(0, i);
//这个pattern有映射,并且等于这段字符;
//或者没有映射,就可以假设这个映射成立并继续尝试匹配剩下的字符
if((map.count(letter) && map[letter] == substr) ||
( !map.count(letter) )
){
map[letter] = substr;
int p = wordPatternMatch(pattern.substr(1), str.substr(i));
if(p){
return true;
}
map.erase(letter);
}
}
return false;
}
};
样本对应模型