返回

C/C++ 1408. 数组中的字符串匹配:优化空间,高效搜索!

后端

题目

给定一个字符串数组 words 和一个字符串 pattern,找出 words 中的所有字符串 word,使得 wordpattern 匹配。

匹配规则定义如下

  • patternword 都由小写英文字母组成。
  • pattern 的长度与 word 的长度相等。
  • pattern 可以包含一个或多个 '' 字符,'' 可以匹配任意字符。

示例 1

输入:words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb"
输出:["mee","aqq"]
解释:
"mee""abb" 匹配,因为 '*' 可以匹配 'e'"aqq""abb" 匹配,因为 '*' 可以匹配 'q'。
其他字符串不匹配 "abb"

示例 2

输入:words = ["a","b","c"], pattern = "a*b*"
输出:["a","b","c"]
解释:
"*" 可以匹配任何字符,因此 "a*b*" 可以匹配 "a""b""c"

提示

  • 1 <= words.length <= 50
  • 1 <= words[i].length <= 50
  • 1 <= pattern.length <= 50
  • wordspattern 都由小写英文字母组成
  • pattern 可以包含一个或多个 '' 字符

题目整理

  • 输入 :字符串数组 words 和字符串 pattern
  • 输出 :所有与 pattern 匹配的字符串 word,其中 '*' 可以匹配任意字符
  • 匹配规则
    • patternword 都由小写英文字母组成
    • pattern 的长度与 word 的长度相等
    • pattern 可以包含一个或多个 '' 字符,'' 可以匹配任意字符

题目的解题思路

这道题目本质上是一个字符串匹配的问题。我们可以使用 KMP 算法或 Trie 树来解决。KMP 算法的时间复杂度为 O(n+m),其中 npattern 的长度,mwords 中所有字符串的总长度。Trie 树的时间复杂度为 O(n+m),其中 npattern 的长度,mwords 中所有字符串的总长度。

由于 KMP 算法和 Trie 树都是比较复杂的算法,因此我们这里使用一种更简单的方法来解决这个问题。

我们可以将 pattern 中的所有字符分为两类:

  • 常规字符:即不是 '*' 的字符
  • 通配符字符:即 '*' 字符

对于常规字符,我们可以直接比较 patternword 中对应位置的字符是否相等。对于通配符字符,我们可以使用以下规则来匹配:

  • 通配符字符可以匹配任意字符
  • 通配符字符可以匹配零个或多个字符

我们可以使用回溯法来枚举所有可能的匹配方案。对于每一个通配符字符,我们可以尝试匹配零个或多个字符。如果匹配成功,我们就继续匹配下一个字符。如果匹配失败,我们就回溯到上一个通配符字符,尝试匹配另一个方案。

使用这种方法,我们可以找到所有与 pattern 匹配的字符串 word

具体的实现和代码

class Solution {
public:
    vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
        vector<string> result;
        for (string& word : words) {
            if (isMatch(word, pattern)) {
                result.push_back(word);
            }
        }
        return result;
    }

private:
    bool isMatch(string word, string pattern) {
        int n = word.size();
        int m = pattern.size();
        if (n != m) {
            return false;
        }
        unordered_map<char, char> patternToWord;
        unordered_map<char, char> wordToPattern;
        for (int i = 0; i < n; i++) {
            char c1 = pattern[i];
            char c2 = word[i];
            if (patternToWord.count(c1) == 0 && wordToPattern.count(c2) == 0) {
                patternToWord[c1] = c2;
                wordToPattern[c2] = c1;
            } else if (patternToWord[c1] != c2 || wordToPattern[c2] != c1) {
                return false;
            }
        }
        return true;
    }
};

总结

这道题目考察的是字符串匹配的基本功。我们可以使用 KMP 算法或 Trie 树来解决这个问题,也可以使用回溯法来枚举所有可能的匹配方案。只要我们能够正确地理解题意,并熟练掌握字符串匹配的算法,我们就可以轻松地解决这个问题。