给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.‘ 和 ‘*‘ 的正则表达式匹配。
‘.‘ 匹配任意单个字符
‘*‘ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
输入:s = "ab" p = "."
输出:true
解释:"." 表示可匹配零个或多个(‘*‘)任意字符(‘.‘)。
输入:s = "aab" p = "cab"
输出:true
解释:因为 ‘*‘ 表示零个或多个,这里 ‘c‘ 为 0 个, ‘a‘ 被重复一次。因此可以匹配字符串 "aab"。
动态规划。难点是初始化和转移方程。
用 \(dp[i][j]\) 表示 \(s\) 的前 \(i\) 个和 \(p\) 的前 \(j\) 个是否匹配,需要讨论 \(p[j+1]\) 是否是 ‘*‘:
难点在于初始化。
首先 \(dp[0][0]=true\)
其次,比如s=‘ab‘,p=‘c*b‘时进行匹配,匹配到s的空子串和p的‘c*‘时应该为真。怎么初始化呢?我的办法是,用一个特殊符号(比如#)来表示s的空子串取到的符号,空子串不应该和任何p的子串匹配。此时的转移路径是 \(dp[0][2]=dp[0][0]=true\) 表示s的空子串和p的子串‘c*‘匹配。
class Solution {
boolean matches(char c1,char c2){
if(c1==‘#‘) return false;
return c1==c2||c2==‘.‘;
}
public boolean isMatch(String s, String p) {
int m=s.length(),n=p.length();
boolean[][] dp=new boolean[m+1][n+1];
dp[0][0]=true;
for(int i=-1;i<m;++i){
for(int j=0;j<n;++j){
char c1=(i==-1?‘#‘:s.charAt(i)),c2=p.charAt(j);
if(c2==‘*‘){
char prev=p.charAt(j-1);
if(matches(c1,prev)){
dp[i+1][j+1]=dp[i+1][j-1]||dp[i][j+1];
}else{
dp[i+1][j+1]=dp[i+1][j-1];
}
}else{
if(matches(c1,c2)){
dp[i+1][j+1]=dp[i][j];
}
}
}
}
return dp[m][n];
}
}
原文:https://www.cnblogs.com/livingsu/p/14886238.html