Given a pattern and a string str, find if strfollows the same pattern.

Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty substring in str.

Example 1:

Input: pattern = "abab", str = "redblueredblue"
Output: true

Example 2:

Input: pattern = pattern = "aaaa", str = "asdasdasdasd"
Output: true

Example 3:

Input: pattern = "aabb", str = "xyzabcxzyabc"
Output: false

Notes:
You may assume both pattern and str contains only lowercase letters.

这道题是之前那道 Word Pattern 的拓展,之前那道题词语之间都有空格隔开,这样可以一个单词一个单词的读入,然后来判断是否符合给定的特征,而这道题没有空格了,那么难度就大大的增加了,因为我们不知道对应的单词是什么,所以得自行分开,可以用回溯法来生成每一种情况来判断,这里还是需要用 HashMap 来建立模式字符和单词之间的映射,还需要用变量p和r来记录当前递归到的模式字符和单词串的位置,在递归函数中,如果p和r分别等于模式字符串和单词字符串的长度,说明此时匹配成功结束了,返回 ture,反之如果一个达到了而另一个没有,说明匹配失败了,返回 false。如果都不满足上述条件的话,取出当前位置的模式字符,然后从单词串的r位置开始往后遍历,每次取出一个单词,如果模式字符已经存在 HashMap 中,而且对应的单词和取出的单词也相等,那么再次调用递归函数在下一个位置,如果返回 true,那么就返回 true。反之如果该模式字符不在 HashMap 中,要看有没有别的模式字符已经映射了当前取出的单词,如果没有的话,建立新的映射,并且调用递归函数,注意如果递归函数返回 false 了,要在 HashMap 中删去这个映射,参见代码如下:

解法一:

class Solution {
public:
bool wordPatternMatch(string pattern, string str) {
unordered_map<char, string> m;
return helper(pattern, , str, , m);
}
bool helper(string pattern, int p, string str, int r, unordered_map<char, string> &m) {
if (p == pattern.size() && r == str.size()) return true;
if (p == pattern.size() || r == str.size()) return false;
char c = pattern[p];
for (int i = r; i < str.size(); ++i) {
string t = str.substr(r, i - r + );
if (m.count(c) && m[c] == t) {
if (helper(pattern, p + , str, i + , m)) return true;
} else if (!m.count(c)) {
bool b = false;
for (auto it : m) {
if (it.second == t) b = true;
}
if (!b) {
m[c] = t;
if (helper(pattern, p + , str, i + , m)) return true;
m.erase(c);
}
}
}
return false;
}
};

下面这种方法和上面那种方法很类似,不同点在于使用了 set,而使用其的原因也是为了记录所有和模式字符建立过映射的单词,这样就不用每次遍历 HashMap 了,只要在 set 中查找取出的单词是否存在,如果存在了则跳过后面的处理,反之则进行和上面相同的处理,注意还要在 set 中插入新的单词,最后也要同时删除掉,参见代码如下:

解法二:

class Solution {
public:
bool wordPatternMatch(string pattern, string str) {
unordered_map<char, string> m;
unordered_set<string> st;
return helper(pattern, , str, , m, st);
}
bool helper(string pattern, int p, string str, int r, unordered_map<char, string> &m, unordered_set<string> &st) {
if (p == pattern.size() && r == str.size()) return true;
if (p == pattern.size() || r == str.size()) return false;
char c = pattern[p];
for (int i = r; i < str.size(); ++i) {
string t = str.substr(r, i - r + );
if (m.count(c) && m[c] == t) {
if (helper(pattern, p + , str, i + , m, st)) return true;
} else if (!m.count(c)) {
if (st.count(t)) continue;
m[c] = t;
st.insert(t);
if (helper(pattern, p + , str, i + , m, st)) return true;
m.erase(c);
st.erase(t);
}
}
return false;
}
};

再来看一种不写 helper 函数的解法,可以调用自身,思路和上面的方法完全相同,参见代码如下:

解法三:

class Solution {
public:
bool wordPatternMatch(string pattern, string str) {
if (pattern.empty()) return str.empty();
if (m.count(pattern[])) {
string t = m[pattern[]];
if (t.size() > str.size() || str.substr(, t.size()) != t) return false;
if (wordPatternMatch(pattern.substr(), str.substr(t.size()))) return true;
} else {
for (int i = ; i <= str.size(); ++i) {
if (st.count(str.substr(, i))) continue;
m[pattern[]] = str.substr(, i);
st.insert(str.substr(, i));
if (wordPatternMatch(pattern.substr(), str.substr(i))) return true;
m.erase(pattern[]);
st.erase(str.substr(, i));
}
}
return false;
}
unordered_map<char, string> m;
unordered_set<string> st;
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/291

类似题目:

Word Pattern

参考资料:

https://leetcode.com/problems/word-pattern-ii/

https://leetcode.com/problems/word-pattern-ii/discuss/73721/My-simplified-java-version

https://leetcode.com/problems/word-pattern-ii/discuss/73664/Share-my-Java-backtracking-solution

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Word Pattern II 词语模式之二的更多相关文章

  1. [LeetCode] 291. Word Pattern II 词语模式 II

    Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...

  2. [LeetCode] Word Search II 词语搜索之二

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

  3. [LeetCode] Word Ladder II 词语阶梯之二

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  4. LeetCode 290. Word Pattern (词语模式)

    Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...

  5. [LeetCode] 212. Word Search II 词语搜索之二

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

  6. [LeetCode] 126. Word Ladder II 词语阶梯之二

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  7. [LeetCode] Word Break II 拆分词句之二

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  8. Leetcode: Word Pattern II

    Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...

  9. [LeetCode] Word Pattern 词语模式

    Given a pattern and a string str, find if str follows the same pattern. Examples: pattern = "ab ...

随机推荐

  1. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  2. 账号密码管理系统Access版本

    哈哈,花了我整整五天时间,账号密码管理系统软件终于成功编写完成了.由于我的各大论坛的账号密码特别多,记性又不好.所以一直以来都想要这么一个软件的,但是以前学习的都是面向过程的编程语言,一直无法实现这个 ...

  3. 《JavaScript 代码优化指南》

      ~~教你向老鸟一样敲代码~~. 1. 将脚本放在页面的底部 ... <script src="./jquery.min.js"></script> &l ...

  4. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  5. 明显调用的表达式前的括号必须具有(指针)函数类型 编译器错误 C2064

    看到“明显调用的表达式前的括号必须具有(指针)函数类型”这句时我才发现我的语文水平有多烂,怎么看都看不懂,折腾了半天才知道是哪里出了问题. 举个简单的例子 class CTest { void (CT ...

  6. 浅析java内存模型--JMM(Java Memory Model)

    在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通 ...

  7. 兼容javascript和C#的RSA加密解密算法,对web提交的数据进行加密传输

    Web应用中往往涉及到敏感的数据,由于HTTP协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息.虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都 ...

  8. React Native windows搭建记录

    因为是window电脑上运行的,所以测试的是安卓 1: 安装jdk:jdk-8u45-windows-x64.exe 2: 配置JAVA的环境变量 在安卓的配置基础上添加一个变量ANDROID_HOM ...

  9. IT菜鸟的生存指南(一)那些人才适合从事IT行业

    此文献给那些刚误入IT行业的小菜鸟们,此文无法教你如何"当上CEO,迎娶白富美",那是电视剧情.现实IT行业里危机重重,竞争激励.这里教你的是如何生存.生存.生存- Just do ...

  10. (十一)Maven远程仓库的各种配置

    1.远程仓库的配置 在平时的开发中,我们往往不会使用默认的中央仓库,默认的中央仓库访问的速度比较慢,访问的人或许很多,有时候也无法满足我们项目的需求,可能项目需要的某些构件中央仓库中是没有的,而在其他 ...