您的位置:首页 > 其它

DP通配符匹配

2019-07-03 21:00 113 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/zb_915574747/article/details/94588951

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。

说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".

可以用递归和DP解,DP挺长时间不用都忘了,大一acm训练看完DP方法就开始刷题,基本是建二维或一维DP数组,找转换方程,填DP,当时分类做的题,上来就是建DP数组,比较机械,硬做。。。时间一长印象不深,现在准备找工作基本都忘了,用这道题好好复习下加一些理解。

DP求解要求最优子结构和子问题重叠,最优子结构保证子问题结合后的解就是整个问题的解,子问题重叠是在递归求解时,每次求解的子问题不总是新问题,有的子问题重复计算,DP利用这个性质,通过建立DP表,只计算子问题一次,然后将结果存储在DP表中,再次用到计算过的子问题时,直接根据状态转移方程查表可以得到当前值,提高效率。

s,p 0 * a * b
0 1 1 0 0 0
a 0 1 1 1 0
d 0 1 0 1 0
c 0 1 0 1 0
e 0 1 0 1 0
b 0 1 0 1 1

根据输入数据建DP表,(0,0)表示两个空字符串匹配,直接设为1(true)。

第一行(a上边的0哪行)为初始化,表示模式串p与空字符串的匹配结果,*与空串匹配为1,*可以匹配空串,a处表示*a与空串匹配,a前面的*可以匹配空,但a不能匹配空,所以*a不能匹配空串,第二个*表示*a*与空串匹配,虽然第二个*能匹配空串,但前面的*a结果是已经不能匹配空串,所以*a*也不能匹配空串,当前的DP表值是按照全面的值推出的,以此类推第一行的b下的值为0。

第一列(*左边0那列)也为初始化,表示模式串p为空,分别与源串匹配,肯定都是空。

从第二行二列(1,1)开始是利用状态转移方程填表,状态转移方程可以表示为:

                                                    DP[i][j]=DP[i-1][j-1]               s[i]==p[j]||p[j]=='?'

                                                    DP[i][j]=DP[i-1][j]||DP[i][j-1]            p[j]=='*'

其中s[i]==p[j]||p[j]=='?'表示当前模式串字符p[j]与源串字符s[i]相同,DP[i][j]=DP[i-1][j-1]表示既然s[i]与p[j]字符相同,那么当前串s(从0到i的字符串)和模式串p(0到j)是否匹配的结果就是它们之前的串(s[0.....i-1],p[0.....j-1])的结果,因为当前字符是相同的。

其中p[j]=='*'表示模式串遇到了*这个字符,*比较特殊,既能匹配空字符串,又能匹配任意字符串。

当匹配了空串时,此时的DP[i][j]值就是s[i]和p[j-1]的值即为DP[i][j-1] 。如s=adc,p=*a*,当比较c与第二个*时,如果第二个*不匹配任何字符串,那么当前的DP[i][j]值就是adc和*a匹配的值,即DP[i][j-1]。

当匹配一个或多个字符时,DP[i][j]值就是s[i-1]和p[j]的值即为DP[i-1][j](匹配多个字符时为DP[i-n][j],由于是迭代逐个求解,求DP[i-n-1][j]时会包含DP[i-n][j]的解,以此类推DP[i-1][j]也就包括了DP[i-n][j],即DP[i-1][j]==DP[i-n][j])。如s=adc,p=*a*,当比较c与第二个*时,如果匹配了一个字符,那么当前的DP[i][j]值就是ad和*a*匹配的值,即DP[i-1][j]。如果匹配了两个字符,那么当前的DP[i][j]值就是a和*a*匹配的值,即DP[i-2][j],但求ad和*a*匹配时已经求出a和*a*是否匹配了,DP[i-1][j]是根据DP[i-2][j]求解的,所以DP[i-1][j]==DP[i-n][j]。

代码:

[code]class Solution {
public:
bool isMatch(string s, string p) {
int src=s.size();
int pa=p.size();
vector<vector<bool>> dp(src+1,vector<bool>(pa+1,false));
dp[0][0]=true;
for(int j=1;j<(pa+1);j++){
if(p[j-1]=='*')
dp[0][j]=dp[0][j-1]&&true;
}
for(int i=1;i<src+1;i++){
for(int j=1;j<pa+1;j++){
if(p[j-1]==s[i-1]||p[j-1]=='?'){
dp[i][j]=dp[i-1][j-1];
}
else if(p[j-1]=='*'){
dp[i][j]=dp[i-1][j]||dp[i][j-1];
}
}
}
return dp[src][pa];
}
};

能力有限,可能理解不对,欢迎交流。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: