题目描述
给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
'?' 可以匹配任何单个字符。 '*' 可以匹配任意字符串(包括空字符串)。 两个字符串完全匹配才算匹配成功。
示例
来自LeetCode来自LeetCode
题目链接
动态规划
可以使用dp[i][j]来保存s的前i个字符与p的前j个字符匹配情况。当p取到‘?’或者两个字符串取出来的字符相同时。只需要看dp[i-1][j-1]的情况即可,也就是之前的字符串匹配情况。if(p[j]==s[i] || p[j]=='?') dp[i][j]=dp[i-1][j-1]
若p取出来的是‘’时,我们需要考虑两种情况,匹配一个空串时,则当s的前i个字符与p的前j-1个字符匹配成功则认为匹配成功。另一种情况则是*匹配s[i],此时若s的前i-1个字符与p的前j个字符匹配成功则认为匹配成功。即if(p[j]=='*')dp[i][j]=dp[i-1][j] || dp[i][j-1]
.
注意,当*匹配是s[i]时,dp[i][j]=dp[i-1][j]
而不是dp[i-1][j-1]
因为匹配一个字符后,*仍然可以继续匹配其他字符或空串,若写成dp[i][j]=dp[i-1][j-1]则意味着抛弃了这个*,它不继续匹配。如s="abc" ,p="a*" *匹配c后我们查看“ab”与“a*”的匹配情况,而不是跳过*直接查看“ab”与"a"的匹配情况。
我们还需要注意边界情况,空串与空串是可以匹配成功的,所以dp[0][0]=true.若p取空串,则dp[i][0]=false(i>0).若s为空则只有当p[0:j]为'*'时dp[0][j]=ture 否则为false。
//dp[i][j]保存s的前i个字符与p的前j个字符匹配情况。
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
dp[0][0] = true;
for (int i = 0; i < p.length(); i++) {//当p的前i个字符均为*时,才能匹配s为空的情况
if (p.charAt(i) == '*')
dp[0][i + 1] = true;
else break;
}
for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) {
if (p.charAt(j - 1) == '*') {//*匹配空串或s的一个字符
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
} else if (p.charAt(j - 1) == '?' || p.charAt(j - 1) == s.charAt(i - 1)) {//单个字符匹配
dp[i][j] = dp[i - 1][j - 1];
}
}
}
return dp[s.length()][p.length()];
动态规划可以通过测试,但效率并不算高。
效率并不理想
据说这题用贪心算法的效率会比动态规划高,有时间研究一下
网友评论