[LeetCode] 291. Word Pattern II 詞語模式之二


 

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, 0, str, 0, 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 + 1);
            if (m.count(c) && m[c] == t) {
                if (helper(pattern, p + 1, str, i + 1, 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 + 1, str, i + 1, 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, 0, str, 0, 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 + 1);
            if (m.count(c) && m[c] == t) {
                if (helper(pattern, p + 1, str, i + 1, m, st)) return true;
            } else if (!m.count(c)) {
                if (st.count(t)) continue;
                m[c] = t;
                st.insert(t);
                if (helper(pattern, p + 1, str, i + 1, 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[0])) {
            string t = m[pattern[0]];
            if (t.size() > str.size() || str.substr(0, t.size()) != t) return false;
            if (wordPatternMatch(pattern.substr(1), str.substr(t.size()))) return true;
        } else {
            for (int i = 1; i <= str.size(); ++i) {
                if (st.count(str.substr(0, i))) continue;
                m[pattern[0]] = str.substr(0, i);
                st.insert(str.substr(0, i));
                if (wordPatternMatch(pattern.substr(1), str.substr(i))) return true;
                m.erase(pattern[0]);
                st.erase(str.substr(0, 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 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM