跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Google 面试题:通配符匹配
未分類
24 10 月 2020

Google 面试题:通配符匹配

Google 面试题:通配符匹配

資深大佬 : zzzrf 5

判断两个可能包含通配符“?”和“*”的字符串是否匹配。匹配规则如下:

  • ‘?’ 可以匹配任何单个字符。

  • ‘*’ 可以匹配任意字符串(包括空字符串)。 两个串完全匹配才算匹配成功。

  • 1<=|s|, |p| <= 1000

  • s 仅包含小写英文字母

  • p 包含小写英文字母,?和 *

在线做题地址

样例 1

输入: "aa" "a" 输出: false 

样例 2

输入: "aa" "aa" 输出: true 

样例 3

输入: "aa" "*" 输出: true 说明: '*' 可以替换任何字符串 

样例 4

输入: "ab" "?*" 输出: true 说明: '?' -> 'a' '*' -> 'b' 

算法:动态规划

dp 方程 dp[i][j]表示 s 中前 i 个字符和 p 的前 j 个字符是否匹配成功,如果匹配成功则为 true,否则为 false

初始条件

  • s,p 为空串时 能匹配成功 所以 dp[0][0]=true
  • s 为空串,p 只为号时候,号也能替换成空串,所以 dp[0][i]=true (p 串从 1 到 i 均是号),如果有除号以外的字符就匹配不上了

方程转移 对于 dp[i][j]

  • p 的第 j 个字符是号,号可以匹配任意串
    • 所以无论是 s 的前 i 个字符和 p 的前 j-1 个字符匹配成功 将*号替换成空串
    • 还是 s 的前 i-1 个字符和 p 的前 j 个字符匹配成功,号替换的长度不限制, 所以可以将号替换成的内容多加上 s[i] 这两种情况都能推出 s 的前 i 个字符和 p 的前 j 个字符匹配成功 if(p[j-1]==’*’) { dp[i][j] = dp[i-1][j] || dp[i][j-1]; }
  • p 的第 j 个字符不是*号
    • 如果 dp[i-1][j-1]为 false, 则 s 的前 i-1 个字符和 p 的前 j-1 个字符已经匹配失败了 这时候 dp[i][j]只能为 false 了
  • 如果 dp[i-1][j-1]为 true,s 的前 i-1 个字符和 p 的前 j-1 个字符已经匹配成功了 则要看 s 的第 i 个字符 s[i] 和 p 的第 j 个字符 p[j]是否匹配成功 s[i]和 p[j]匹配成功有两种情况 1 是两个字符相同,2 是 p[j]是? else { if(dp[i-1][j-1] == true) { if(s[i-1]==p[j-1] || p[j-1]==’?’){ dp[i][j]=true; } } }

注意事项

我们 dp 数组下标为 0 的地方要表示空串的答案,所以 dp[i][j]是 s 串的前 i 个字符和 p 串前 j 个字符,这里的 i 和 j 的记数不是从 0 开始的

复杂度分析

时间复杂度

dp 数组状态是 O(NM)的,转移是 O(1)的 所以总时间复杂度是 O(NM)的 N 是 s 串长度,M 是 p 串长度

空间复杂度

dp 数组空间 O(NM)

代码

public class Solution {     public boolean isMatch(String s, String p) {         int sLen = s.length();         int pLen = p.length();         //为了空出边界条件 dp[0][0] 我们 dp 数组从下标为 1 开始使用         // dp[i][j]表示 s 中前 i 个字符和 p 的前 j 个字符是否匹配成功,如果匹配成功则为 true          //初始化 dp 数组         boolean [][]dp = new boolean[sLen + 5][pLen + 5];         for(int i = 0; i <= sLen; i++) {             for(int j = 0; j <= pLen; j++) {                 dp[i][j] = false;             }         }         dp[0][0] = true;          //s 为空,*也可以替换成空串,则当 s 为空 p 为连续的*号时候也是匹配成功的         for(int i = 1; i <= pLen; i++) {             if(p.charAt(i - 1) == '*') {                 dp[0][i] = dp[0][i - 1];             }         }          for(int i = 1; i <= sLen; i++) {             for(int j = 1; j <= pLen; j++) {                 //p 的第 j 个字符是*号,*号可以匹配任意串                 //所以无论是 s 的前 i 个字符和 p 的前 j-1 个字符匹配成功 将*号替换成空串                 //还是 s 的前 i-1 个字符和 p 的前 j 个字符匹配成功,*号替换的长度不限制,                 //所以可以将*号替换成的内容多加上 s[i]                 // 这两种情况都能推出 s 的前 i 个字符和 p 的前 j 个字符匹配成功                 if(p.charAt(j - 1) == '*') {                     dp[i][j] = dp[i - 1][j] || dp[i][j - 1];                 }                  //p 的第 j 个字符不是*号                 //如果 dp[i-1][j-1]为 false,                 //则 s 的前 i-1 个字符和 p 的前 j-1 个字符已经匹配失败了                 //这时候 dp[i][j]只能为 false 了                 // 如果 dp[i-1][j-1]为 true,s 的前 i-1 个字符和 p 的前 j-1 个字符已经匹配成功了                 //则要看 s 的第 i 个字符 s[i] 和 p 的第 j 个字符 p[j]是否匹配成功                 //s[i]和 p[j]匹配成功有两种情况 1 是两个字符相同,2 是 p[j]是?                 else {                     if(dp[i - 1][j - 1] == true) {                         if(s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') {                             dp[i][j] = true;                         }                     }                 }             }         }         return dp[sLen][pLen];      } } 

大佬有話說 (0)

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具