题意:

image.png

解题思路:

  1. 状态定义:dp[i][j] : 表示 s 的前i个字符和p的前j个字符是否匹配(true的话表示匹配)
  2. 状态转移方程:
  3. 1. s[i] == p[j],或者 p[j] == ? 那么 dp[i][j] = dp[i - 1][j - 1];
  4. 2. p[j] == * 那么 dp[i][j] = dp[i][j - 1] || dp[i - 1][j]
  5. 其中:
  6. dp[i][j - 1] * 代表的是空字符,例如 ab, ab* //*可以代表空,匹配个数[0个]
  7. dp[i - 1][j] * 代表的是非空字符,例如 abcd, ab* //*代表cd,匹配个数[多个]
  8. dp[i - 1][j - 1] //abc ab* *代表c,匹配个数[1个]
  9. 初始化:
  10. 1. dp[0][0] 表示什么都没有,其值为 true
  11. 2. 第一行 dp[0][j],换句话说,s 为空,与 p 匹配,所以只要 p 开始为 * 才为 true
  12. 3. 第一列 dp[i][0],当然全部为 false

PHP代码实现:

  1. class Solution {
  2. function isMatch($s, $p) {
  3. // 状态 dp[i][j] : 表示 s 的前 i 个字符和 p 的前 j 个字符是否匹配
  4. $dp = [];
  5. // 初始化
  6. $dp[0][0] = true;
  7. for ($j = 1; $j <= strlen($p); $j++) {
  8. if ($p[$j - 1] == '*') {
  9. $dp[0][$j] = $dp[0][$j - 1];
  10. } else {
  11. $dp[0][$j] = false;
  12. }
  13. }
  14. for ($i = 1; $i <= strlen($s); $i++) {
  15. $dp[$i][0] = false;
  16. }
  17. // 状态转移
  18. for ($i = 1; $i <= strlen($s); $i++) {
  19. for ($j = 1; $j <= strlen($p); $j++) {
  20. if ($s[$i - 1] == $p[$j - 1] || $p[$j - 1] == '?') {
  21. $dp[$i][$j] = $dp[$i - 1][$j - 1];
  22. } else if ($p[$j - 1] == '*') {
  23. $dp[$i][$j] = $dp[$i][$j - 1] || $dp[$i - 1][$j] || $dp[$i - 1][$j - 1];
  24. } else {
  25. $dp[$i][$j] = false;
  26. }
  27. }
  28. }
  29. return $dp[strlen($s)][strlen($p)];
  30. }
  31. }
  1. /* 贪心算法
  2. a d c e b
  3. * a * b
  4. 1. $sBegin = 0 $pBegin = 0; j++
  5. 2. $sBegin = 2 $pBegin = 1; j++
  6. 3. j = b
  7. */
  8. class Solution {
  9. function isMatch($s, $p) {
  10. return $this->isMatchDp($s, $p);
  11. $m = strlen($s);
  12. $n = strlen($p);
  13. $i = 0; $j = 0;
  14. $sBegin = -1; $pBegin = -1;
  15. while ($i < $m) {
  16. //两个字符相等或者p是问号
  17. if ($j < $n && $s[$i] == $p[$j] || $p[$j] == '?') {
  18. ++$i; ++$j;
  19. } else if ($j < $n && $p[$j] == '*') {//不等,但是p是星号
  20. ++$j;
  21. $sBegin = $i;
  22. $pBegin = $j;
  23. } else if ($pBegin != -1) {
  24. ++$sBegin;
  25. $i = $sBegin;
  26. $j = $pBegin;
  27. } else return false;
  28. }
  29. while ($j < $n && $p[$j] == '*') ++$j;
  30. return $j == $n;
  31. }
  32. }

GO代码实现:

  1. func isMatch(s string, p string) bool {
  2. sLen, pLen := len(s), len(p)
  3. dp := make([][]bool, sLen + 1)
  4. for i := 0; i < len(dp); i++ {
  5. dp[i] = make([]bool, pLen + 1)
  6. }
  7. dp[0][0] = true
  8. for i := 1; i < pLen + 1; i++ {
  9. dp[0][i] = dp[0][i - 1] && p[i - 1] == '*'
  10. }
  11. for i := 1; i < sLen + 1; i++ {
  12. for j := 1; j < pLen + 1; j++ {
  13. if s[i - 1] == p[j - 1] || p[j - 1] == '?' {
  14. dp[i][j] = dp[i - 1][j - 1]
  15. } else if p[j - 1] == '*' {
  16. dp[i][j] = dp[i][j - 1] || dp[i - 1][j] || dp[i - 1][j - 1]
  17. } else {
  18. dp[i][j] = false
  19. }
  20. }
  21. }
  22. return dp[sLen][pLen]
  23. }