leetcode:291. 单词规律

题目来源

题目描述

在这里插入图片描述

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;
    }
};

样本对应模型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值