日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[LeetCode] Wildcard Matching 题解

發布時間:2025/4/14 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [LeetCode] Wildcard Matching 题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

6. Wildcard Matching

題目

Implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:bool isMatch(const char *s, const char *p)

Some examples:isMatch("aa","a") ? falseisMatch("aa","aa") ? trueisMatch("aaa","aa") ? falseisMatch("aa", "*") ? trueisMatch("aa", "a*") ? trueisMatch("ab", "?*") ? trueisMatch("aab", "c*a*b") ? false

解答

DFS

這里的難點在于如何處理*,因為這個星號可以代表0到多個字符,而且有可能會遇到遞歸一開始匹配正確后面不正確,但實際上應該從后面開始匹配。

class Solution(object):# p為匹配模式,s為字符串def recursive(self, s, p, si, pi, cur):first = Truen_cur = curwhile si < len(s) and pi < len(p) and (s[si] == p[pi] or p[pi] == '?'):si += 1pi += 1if pi == len(p):return si == len(s)if p[pi] == '*':while pi < len(p) and p[pi] == '*':pi += 1if pi >= len(p):return Truefor i in range(si, len(s)):# 表明開始重合,從這里再度開始遞歸if p[pi] != s[i] and p[pi] != '?':continueif first:cur += 1first = False# 可能存在多次重合但是還不算真正匹配的情況if self.recursive(s, p, i, pi, cur + 1):return Trueif cur > n_cur + 1: # 正常來說n_cur = cur + 1return Falsereturn Falsedef isMatch(self, s, p):""" :type s: str :type p: str :rtype: bool """return self.recursive(s, p, 0, 0, 0)

這種做法超時。

DP

我們定義一個二維數組dp,橫坐標為待匹配字符串,縱坐標為模式字符串,dp[i][j]則代表到模式字符串從0到 i 對應待匹配字符串的的0到 j 是否是匹配的。舉個例子:

pattern = "a*bc" str = "abbc"

我們可以根據前面提到的畫出整個二維數組

\\abbc
\TFFFF
aFTFFF
*FTTTT
bFFTTF
cFFFFT

我們可以發現一個規律,每當遇到兩個字符不相等的時候,那么數組的值則肯定是False,相反相等的時候肯定是True,這里需要注意的是*,這里則需要考慮到它當前可能匹配0個字符串或者匹配多個字符,比如上面中的a*和ab的情況,此時我們需要發現a*及a或者a和ab其中有任何一個成功匹配的,它的結果也肯定為T。

這個狀態轉義方程要怎么推算出來呢?

  • 如果p.charAt(i)=='*','*'可以選擇匹配0個字符,此時flag[i][j]=flag[i-1][j];可以選擇匹配1個字符,此時flag[i][j]=flag[i-1][j-1];……所以可以得到下面的公式:

  • 因為flag[i][j]=flag[i-1][j]||flag[i-1][j-1]||……||flag[i-1][0],我們可以代入上面的公式得到:

  • 于是我們可以很簡單的寫出程序了(下面的程序的i,j和狀態轉義方程是相反的,但是原理是相同的)

    class Solution(object):# p為匹配模式,s為字符串def isMatch(self, s, p):""" :type s: str :type p: str :rtype: bool """if len(s) != len(p) - p.count('*'):return Falsenewp = ""i = 0while i < len(p):newp += p[i]if p[i] == '*':while i + 1 < len(p) and p[i + 1] == '*':i += 1i += 1sl, pl = len(s), len(newp)dp = [[False for x in range(pl + 1)] for y in range(sl + 1)]dp[0][0] = Trueif pl > 0 and p[0] == '*':dp[0][1] = Truefor x in range(1, sl + 1):for y in range(1, pl + 1):if newp[y - 1] != '*':dp[x][y] = dp[x - 1][y - 1] and (s[x - 1] == newp[y - 1] or newp[y - 1] == '?')else:dp[x][y] = dp[x - 1][y] or dp[x][y - 1]return dp[sl][pl]

    同樣的原理,我們還可以把它縮減成一維數組,你可以把它想象成在二維數組中計算每一行的數據,如果遇到*則更新當前行的數據;為什么可以這么做呢?我們可以根據前面提到的公式發現,其中當前的數據依賴于j的變化,也就是待匹配字符串的值,我們還需要在外面寫個模式串的循環,其實和二維數組的做法的時間復雜度是一樣的,但是縮減了空間,但是并不是所有的都可以這么做,這個取決于你的依賴項是什么。總而言之,其原理還是一樣的,只是想辦法讓它們的數據能夠共存到一維數組中。

    class Solution:# @return a booleandef isMatch(self, s, p):length = len(s)if len(p) - p.count('*') > length:return Falsedp = [True] + [False]*lengthfor i in p:if i != '*':# 因為依賴項是前面的值,所以不能從前面往后面掃,得從后往前計算for n in reversed(range(length)):dp[n+1] = dp[n] and (i == s[n] or i == '?')else:# 更新當前行的數據for n in range(1, length+1):dp[n] = dp[n-1] or dp[n]dp[0] = dp[0] and i == '*'return dp[-1]

    貪心算法

    下標描述
    si待匹配字符串的移動下標
    pi模式串的移動下標
    lastmatch上一次匹配的待匹配字符串的下標
    laststar上一次匹配的模式串的下標
  • 如果當前相等或者模式串中字符為?,則移動相互的下標即可;
  • 如果當前模式串字符為*,分別紀錄lastmatch、laststar,并且移動模式串下標,但是不移動待匹配字符串下標,因為可能存在匹配0個字符串的情況;
  • 如果當前相互對應的字符不再相等且不為*,如果前面有*號,說明之前的匹配失敗了,模式字符串下標回到之前紀錄laststar的后一位,不再移動,專門用來給待匹配字符串字符來匹配,這段時間內,si會不斷的向前移動,直到匹配到相互的值相等才移動模式字符串的下標;
  • 如果前面的情況都不符合,則肯定為False;
  • 看看我的抽象派畫風。

    class Solution(object):# p為匹配模式,s為字符串def isMatch(self, s, p):si, pi = 0, 0lastmatch, laststar = -1, -1sl, pl = len(s), len(p)if pl - p.count('*') > sl:return False# 注意條件順序while si < sl:if pi < pl and (s[si] == p[pi] or p[pi] == '?'):pi += 1si += 1elif pi < pl and p[pi] == '*':lastmatch, laststar = si, pi # 之所以不更新lastmatch是因為考慮到*只匹配0個字符串pi += 1# 再次進到這個判斷,說明當前下標對應的值不相等elif laststar != -1:pi = laststar + 1 # pi當前不是*,并且回到上一次星的后面,專門用來給si匹配lastmatch += 1 # 必須更新lastmatch,因為之前已經不想等,如果在回到開始的狀態就會陷入死循環si = lastmatchelse:return False# 可能存在p的末尾都是*的情況while pi < len(p) and p[pi] == '*':pi += 1# 最后匹配成功模式字符串的下標必然為其長度,表示已經匹配完成return pi == pl

    tips:不要小看保存你的長度值,如果你頻繁的用到的話,最好保存下來,比如在這里,我保存下來以后可以讓我提升%10的beat submissions!

    一樣的原理,但是使用了遞歸的方式來做

    class Solution(object):def isMatch(self, s, p):""" :type s: str :type p: str :rtype: bool """seen = {}wild_single, wild_multi = "?", "*"# seen has the pattern - source tuple as key, and bool result as successsource, pattern = s, pdef is_match(sindex, pindex):key = (sindex, pindex)if key in seen:return seen[key]result = True# if there's no string, and pattern is not only * then failif sindex >= len(source):for wildindex in xrange(pindex, len(pattern)):if pattern[wildindex] != wild_multi:result = Falsebreak# there's a string, but no patternelif pindex >= len(pattern):result = False# if next pattern is multi though, that's somethingelif pattern[pindex] == wild_multi:# for zero, simply check sindex, pindex + 1result = is_match(sindex, pindex + 1) # just for easier debug# if zero, than it's a match# otherwise we need to check multi# for that, if char is not a wild, then it has to match the source,result = result or is_match(sindex + 1, pindex)else:# either a regular char, or wild_singleresult = (( pattern[pindex] == wild_single or pattern[pindex] == source[sindex]) and is_match(sindex + 1, pindex + 1))seen[key] = resultreturn resultif (len(p) - p.count(wild_multi) > len(s)):return Falsereturn is_match(0, 0)

    轉載于:https://www.cnblogs.com/George1994/p/7182866.html

    總結

    以上是生活随笔為你收集整理的[LeetCode] Wildcard Matching 题解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产女人高潮的av毛片 | 九一爱爱| 人人妻人人做人人爽 | 97综合视频 | 一区二区三区视频在线观看免费 | 超碰网址| 日本一级一片免费视频 | 成年人免费看黄色 | 麻豆成人入口 | 嫩草天堂 | 亚洲高清一区二区三区 | 激情片| www.亚洲色图 | 免费看黄视频的网站 | 三级成人网 | 日本精品在线播放 | 久久久欧美 | 狠狠躁天天躁夜夜躁婷婷 | 99ri国产精品 | 国产精品成人一区二区三区电影毛片 | 国产精品人人爽人人爽 | 高清一区二区在线 | 男人天堂亚洲 | 丰满肥臀噗嗤啊x99av | 视频免费在线观看 | 国产女主播自拍 | 人妻久久久一区二区三区 | 黄色大全免费观看 | 久久夜色精品国产噜噜亚洲av | 日韩av不卡在线观看 | 在线欧美国产 | 精品久久久久中文慕人妻 | 国产亚洲精品久久久久久打不开 | 办公室荡乳欲伦交换bd电影 | 一级黄色小视频 | 成人一区二区三区在线观看 | 韩日一区二区三区 | 大肉大捧一进一出好爽视频动漫 | 国产精品久久久无码一区 | 人人草人人射 | 麻豆传媒在线观看 | 日日射天天射 | 韩国jizz| 欧州一区二区 | 在线看的av网站 | 玖草视频在线 | 99插插| 色欲av永久无码精品无码蜜桃 | 8x8ⅹ成人永久免费视频 | 开心激情播播网 | 灌篮高手全国大赛电影 | 婷婷色在线播放 | 亚洲欧美制服丝袜 | 国产浪潮av | 免费在线黄色av | 婷婷调教口舌奴ⅴk | 亚洲精品乱码久久久久久久 | 亚洲精品一区二区三区四区 | 久久色网| 无码精品a∨在线观看中文 福利片av | 色人阁网站 | 中文字幕永久在线播放 | 国产精品一区二区三区在线看 | 99免费在线观看 | 搞黄视频在线观看 | 开心激情网站 | 欧美在线视频免费播放 | 手机看片国产1024 | 色婷婷欧美| www四虎影院 | 欧美黄色一区二区三区 | 一区二区国产精品视频 | 亚洲国产经典 | 福利一区二区在线观看 | 国产女主播喷水视频在线观看 | 9.1成人看片免费版 日韩经典在线 | 国产91免费视频 | 日日爱影视 | 欧美精品一区二区在线观看 | 国产乱人视频 | 精品一区二区视频在线观看 | 国产在线观看一区二区三区 | 久久久社区 | 国产豆花视频 | 亚洲色图制服诱惑 | 激情高潮呻吟抽搐喷水 | 欧美日日操| 国产精品无码免费播放 | 97人妻精品一区二区三区视频 | 天堂在线v| 黑人极品ⅴideos精品欧美棵 | 强伦人妻一区二区三区视频18 | 亚洲精品视频大全 | 亚洲视频在线免费观看 | 国产人妖在线视频 | 欧美一级片在线免费观看 | 亚洲第一黄色 | 足交在线观看 | 国产3级在线 |