leetcode笔记 动态规划在字符串匹配中的应用

0 参考文献

序号 标题
1 一招解决4道leetcode hard题,动态规划在字符串匹配问题中的应用
2 10.Regular Expression Matching

1. [10. Regular Expression Matching]

1.1 题目

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.

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

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like . or *.

Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".

Example 5:

Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

1.2 思路 && 解题方法

首先建立一个二维数组,数P组的列是代表了字符串S,数组的行代表了字符串P。dp[i] [j] 表示P[0:i] 匹配S[0:j]。因此如果最后P能够匹配S,则dp [len(P)] [len(S)] == True 。注意dp[0] [0] 分别是S是空字符和P是空字符的时候。 这个时候是必定匹配的,因此dp [0] [0] = True。

之后需要做的事情就是依次填满这个矩阵。为此需要初始化dp [ 0 ] [ j ] 和dp [ i ] [ 0 ]既第0行和第0列。

  1. 对于第0行因为P为空,则除了S是空以外其他的都不匹配。因此 dp [ 0 ] [ j ] = False

  2. 对于第0列,则需要判断下P是否能匹配S是空串的情况。在S是空串的情况下,之后P是空串或者P是带有 " * "的情况下才能匹配,因此只需要处理这两种情况。

    1. P是空串的情况下,可以匹配S。因此dp [ 0 ] [ 0 ] = True
    2. P是" * "的情况下,例如"abc",因为可以是匹配0个或者多个字符。因此当在这种情况下,*号其实可以消掉前面的字符变成""。因此dp [ i ] [ 0 ] = dp [ i-2 ] [ 0 ] and P [ i -1 ] == " * "。这里为什么不是判断dp [ i -1 ] [ 0 ] 是否为True 而是判断dp [ i-2 ] [ 0 ]呢?是因为dp [ i-1 ] [ 0 ]是表示 P [ 0 : i - 2 ] 能够匹配S [ 0 ],如果P [ 0 : i -2 ]能够匹配S [ 0 ],那么当前字符" * " 消掉前一个字符便无法匹配S [ 0 ] (既dp [ i ] [ 0 ] == False)。如下图的示例,当P="a * b * " 是可以匹配""空字符的。那么当i = 2 ,j = 0 的时候,必须有dp [ 0 ] [ 0 ] == True 才能得到 dp [ 2 ] [ 0 ] == True。

到此,dp矩阵的初始化已经好了。这个时候,矩阵中的值如图所示。绿色部分是已经初始化的值。空白的部分是待填充的。

接下来就是填充dp矩阵的剩余部分。对于dp [ i ] [ j ] ( i>1, j>1)会有以下的几种情况:

  1. P [ i - 1 ] == " * " :

    对于这种情况,还可以区别2中情况:

    1. " * " 抵消前面的字符,既 " * "匹配空字符串:

      对于这种情况则和前文所述的方法一样,dp [ i ] [ j ] == dp [ i-2 ] [ j ]

    2. " * "匹配前面的字符N次 :

      对于这种情况,则需要在 ( ( P[ i - 1 ] == " . " ) or ( S[ j -1 ] == P [ i -2 ] ) )的情况下 ,dp [ i -1 ] [ j ] == True。这是为什么呢?原因在于如果要匹配0-N次,则代表了P[ 0 - i -2 ] (既dp [ i -1 ] [ XXXX ] ) 能完全匹配S[ 0 : j - 1 ]。

      如例子中的 "a." 能匹配 "abb"。

  2. P [ i - 1 ] == " . " or P [ i - 1 ] == " 一个正常的字符 " :

    如果是这种情况见简单的多,既( S [ j - 1 ] == P [ j -1 ] or P [ j -1 ] == " . " ) and dp [ i - 1 ] [ j -1 ] == True 。

1.3 实现

class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
# dp[i][j] 代表了p字符串从0-i是否匹配s字符的0-j
row = len(p) + 1
col = len(s) + 1
dp = [ [False for i in range( col ) ] for j in range( row ) ]
dp[0][0] = True # dp[0][0] 代表了p是空串 s是空串
# 当s时空串的情况下,p的不同,匹配的不同情况。为接下去匹配len(s) = 1 ,2 ,3 .... n 做准备
# 当s为空串的时候,只有a*b*这种能匹配。
# 因此dp[0][0] 为空串,所以i-1实际真正指向p的一个字符串的位置
for i in range( 1, row):
dp[i][0] = ( i > 1 ) and p[ i - 1 ] == "*" and dp[ i - 2 ][0] for i in range( 1, row ) :
for j in range( 1, col ): if p[ i - 1 ] =="*":
dp[i][j] = dp[ i - 2 ][j] or ( p[ i - 2 ] == s[ j - 1 ] or p[ i - 2 ] == ".") and dp[i][j-1] else:
dp[i][j] = ( p[ i - 1 ] == "." or p[ i - 1 ] == s[ j - 1 ]) and dp[i-1][j-1] return dp[row-1][col-1]

2. [44. Wildcard Matching]

2.1 题目

Given an input string (s) and a pattern (p), 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).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like ? or *.

Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.

Example 3:

Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.

Example 4:

Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Example 5:

Input:
s = "acdcb"
p = "a*c?b"
Output: false

2.2 思路 && 解题方法

这道题和前面的那道题思路是一样的,也是维护一个二维数组dp 来解题。只不过这里匹配任意字符的符号换成了"?" ,而" * "现在是可以匹配任意序列包括空字符串。 同样的假设当前S= "abc" P="a?b*",则有如下的dp数组:

同样首先初始化第0行和第0列。

  1. 对于第0行很好处理,除了0,0位置,其他的地方全部都是False
  2. 对于第0列,因为S=""因此只有当遇到了" * "的时候,才能匹配。则匹配的条件是dp [ i -1 ] [ 0 ] == True 。

开始填充dp的时候,也是有如下的2种情况:

  1. 当P [ i-1 ] == " * " :

    这种情况下也分2种情况:

    1. " * "当做空字符串使用:则和前述一样 dp [ i ] [ j ] =( dp [ i -1 ] [ j ] == True )
    2. " * "当做任意字符串使用 : 则 dp [ i ] [ j ] = ( dp [ i ] [ j - 1 ] == True)。这里解释下我的理解。对于" * "当做任意字符使用的情况下,dp [ i ] [ j - 1 ] == True 表示的是:P [ 0 : i-2 ] 匹配了 S [ 0 : j -2 ],同时P[ i - 1 ] (当前是 * )当做空子串使用。
  2. 当P [ i-1 ] == " ? " 或 " 一个正常的字符 ":

    则( S [ j - 1 ] == P [ j -1 ] or P [ j -1 ] == " ?" ) and dp [ i - 1 ] [ j -1 ] == True

2.3 实现

#!/bin/python

class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
row = len(p) + 1
col = len(s) + 1
dp = [ [False for i in range( 0, col )] for j in range( 0, row ) ] dp[0][0] = True
for j in range(1, col ):
dp[0][j] = False
for i in range( 1, row):
if p[i-1] == "*":
dp[i][0] = dp[i-1][0] for i in range( 1, row ):
for j in range( 1, col ):
if p[i-1] == "*":
dp[i][j] = dp[i-1][j] or dp[i][j-1]
else:
dp[i][j] = (s[j-1] == p[i-1] or p[i-1] == "?") and dp[i-1][j-1]
return dp[row-1][col-1] if __name__ == "__main__":
m = Solution()
print "s:[aa],p[a] ret:"+str(m.isMatch("aa","a"))
print "s:[aa],p[*] ret:"+str(m.isMatch("aa","*"))
print "s:[cb],p[?a] ret:"+str(m.isMatch("cb","?a"))
print "s:[],p[] ret:"+str(m.isMatch("",""))
print "s:[acdcb],p[a*c?b] ret:"+str(m.isMatch("acdcb","a*c?b"))
print "s:[adceb],p[*a*b] ret:"+str(m.isMatch("adceb","*a*b"))

3. [97. Interleaving String]

3.1 题目

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false

3.2 思路 && 解题方法

本题的思路还是一样的,维护一个动态数组dp 。dp [ i ] [ j ] 表示 S1 [ i ] 和S2 [ j ] 能匹配 S3 [ i + j - 1] 。假设S1="aa" S2="ab" S3="aaba" , 则从dp [ 0 ] [ 0 ]开始,往右一步代表使用S2 [ j ] 表示S3 [ 0 + j ] ( 0 是 i 因为此处是第一行,所以i是0)。同样往下一步 代表使用S1[ i ] 表示 S3 [ i + 0 ] 。因此如果可以到达dp [ i ] [ j ]则 需要 dp [ i -1 ] [ j ]或者 dp [ i ] [ j -1 ]是1 。

3.3 实现

#!/bin/bash

class Solution(object):
def isInterleave(self, s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
row = len(s1) + 1
col = len(s2) + 1
t = len(s3)
if row + col -2 !=t :
return False
dp = [ [False for j in range(col)] for j in range(row) ]
dp[0][0] = True
for j in range(1,col):
dp[0][j] = dp[0][j-1] and s2[j-1] == s3[j-1]
for i in range(1,row):
dp[i][0] = dp[i-1][0] and s1[i-1] == s3[i-1] for i in range(1,row):
for j in range(1,col): dp[i][j] = ( dp[i-1][j] and s1[i-1] == s3[i+j-1]) or (dp[i][j-1] and s2[j-1] == s3[i+j-1])
return dp[row-1][col-1] if __name__=='__main__':
m = Solution()
print m.isInterleave("a","b","a")

leetcode笔记 动态规划在字符串匹配中的应用的更多相关文章

  1. Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用

    P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...

  2. LeetCode 44 Wildcard Matching(字符串匹配问题)

    题目链接:https://leetcode.com/problems/wildcard-matching/?tab=Description   '?' Matches any single chara ...

  3. LeetCode 686. 重复叠加字符串匹配(Repeated String Match)

    686. 重复叠加字符串匹配 686. Repeated String Match 题目描述 给定两个字符串 A 和 B,寻找重复叠加字符串 A 的最小次数,使得字符串 B 成为叠加后的字符串 A 的 ...

  4. Leetcode 686.重复叠加字符串匹配

    重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd", ...

  5. Java实现 LeetCode 686 重复叠加字符串匹配

    686. 重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd&q ...

  6. leetcode——Implement strStr() 实现字符串匹配函数(AC)

    Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if need ...

  7. 字符串匹配KMP算法详解

    1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...

  8. 模糊字符串匹配:FuzzyWuzzy

    FuzzyWuzzy 模糊字符串匹配,它使用Levenshtein Distance来计算简单易用的包中序列之间的差异. 前置条件 Python 2.7 or higher difflib pytho ...

  9. LeetCode 10 Regular Expression Matching(字符串匹配)

    题目链接 https://leetcode.com/problems/regular-expression-matching/?tab=Description   '.' Matches any si ...

随机推荐

  1. ubuntu进不去桌面

    今天折腾ubunu的时候,总是进不去桌面,开机直接进入啦终端模式.在google帮助终于解决. sudo apt install --reinstall gnome-shell ubuntu-desk ...

  2. 通通玩blend美工(7)——简约而不简单的块

    原文:通通玩blend美工(7)--简约而不简单的块 最近在研发一个WPF快速开发框架,满脑子都是各种逻辑各种模式,写一篇比较休闲娱乐的博客,宣泄下我对美工的热爱. 我一直以来有意无意在手机应用或者各 ...

  3. Windows 10开发基础——XML和JSON (二)

    主要内容: Linq to XML Newtonsoft.Json.Linq来解析JSON 博客园RSS(http://www.cnblogs.com/rss)的解析 UWP调用自己实现的Web AP ...

  4. System.Data.SQLite 中GUID的处理

    原文:System.Data.SQLite 中GUID的处理 项目中正好用到System.Data.SQLite,在手持上使用这个数据库,因为要做数据同步,所以表中的主键都是Guid的数据类型. 在数 ...

  5. HLS(HTTP Live Streaming)学习和探讨

    Introduction HTTP Live Streaming lets you send audio and video over HTTP from an ordinary web server ...

  6. 水晶报表异常“CrystalDecisions.ReportSource.ReportSourceFactory”的类型初始值设定项引发异常,未能加载文件或程序集“log4net

    System.TypeInitializationException: “CrystalDecisions.ReportSource.ReportSourceFactory”的类型初始值设定项引发异常 ...

  7. ASP.NET MVC5快速入门--MyFirstWeb并发布到Windows Azure上

    博主刚刚学习ASP.NET MVC5,看着微软的文档一点点学,就把FirstWeb的建立展示一下下啦,本次建立一个带个人身份验证的例子(即有注册登录机制的动态网页),开始,啦啦啦~~ 新建一个项目,选 ...

  8. Qt编译和使用boost库(附QT5.51的Boost下载)good

    配置gcc可以在cmd中使用 添加MinGW到环境变量 安装过Qt的都已经默认安装过MinGw的环境了,只需要找到配置一下环境变量就行 我的在D:\Qt5.5.1\Tools\mingw492_32\ ...

  9. layer 1.9.2 发布,国产 Web 弹层不懈的前行者

    快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中.   <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...

  10. Westciv Tools主要为CSS3提供了渐变gradients、盒子阴影box-shadow、变形transform和文字描边四种在线生成效果的工具

    Westciv Tools主要为CSS3提供了渐变gradients.盒子阴影box-shadow.变形transform和文字描边四种在线生成效果的工具 1.Westciv Tools 彩蛋爆料直击 ...