[程序员代码面试指南]字符串问题-字符串匹配问题(DP)
问题描述
- 字符串str,模式串exp。
- 必须保证str中无'.'和'星号'字符,并且exp中'星号'不出现在首位,且无连续两个'星号'。PS星号是字符只是暂时没找到markdown的星号转义字符。
- '.'可以匹配任意一个字符,'星号'可以匹配0-多个星号前面的一个字符的情况。
- 输出可否匹配。
- 例:
str="abc",exp="a.c" ,true
str="abc",exp=".星号",true
str="",exp="..星号",false
解题思路
- 递归思路写成DP。时间复杂度O(N^2*M), 其中N为str的长度。
- 具体的,
- dp[i][j]表示str[i:str.length]能否匹配exp[j:exp.length]
- 开dp[str.length()+1][exp.length()+1]
- dp[i][j]只依赖于dp[i+k(k>=0)][j+2]或者dp[i+1][j+1],所以初始化最后一行和最后两列,具体初始化看书,并由右下角开始遍历即可。
- 分以下情况讨论转移,具体见书P318.
- 当前位置exp的下一位不是'星号'
- 当前位置exp的下一位是'星号'
- 当前字符匹配
- 当前字符不匹配
代码
public class Main {
public static void main(String args[]) {
String str="";
String exp=".*";
boolean match=isMatch(str,exp);
System.out.println(match);
}
public static boolean isMatch(String str,String exp) {
if(!isValid(str,exp)) {
return false;
}
boolean[][] dp=new boolean[str.length()+1][exp.length()+1];
init(dp,str,exp);
for(int i=str.length()-1;i>=0;--i) {
for(int j=exp.length()-2;j>=0;--j) {
if(exp.charAt(j+1)!='*') {//下一位是星号
if((str.charAt(i)==exp.charAt(j)||exp.charAt(j)=='.')&&dp[i+1][j+1]) {//
dp[i][j]=true;
}
}
else {//下一位不是星号
for(int ii=i;i<str.length()&&((str.charAt(ii)==exp.charAt(j)||exp.charAt(j)=='.'));++ii) {//当前位置可以匹配 //
if(dp[ii+1][j+2]) {
dp[i][j]=true;
break;
}
}
if(!dp[i][j]) {//当前位置不可以匹配
dp[i][j]=dp[i][j+2];
}
}
}
}
return dp[0][0];
}
public static boolean isValid(String str,String exp) {
for(int i=0;i<str.length();++i) {
if(str.charAt(i)=='.'||str.charAt(i)=='*') {
return false;
}
}
for(int i=0;i<exp.length();++i) {
if(exp.charAt(i)=='*'&&(i==0)||i!=0&&exp.charAt(i-1)=='*') {
return false;
}
}
return true;
}
public static void init(boolean[][] dp,String str,String exp) {
for(int i=0;i<=str.length();++i) {//包含初始化最后一列
for(int j=0;j<=exp.length();++j) {
dp[i][j]=false;
}
}
dp[str.length()][exp.length()]=true;
if(str.length()>0&&exp.length()>0) {//初始化倒数第二列 //
if(str.charAt(str.length()-1)==exp.charAt(exp.length()-1)||exp.charAt(exp.length()-1)=='.') {
dp[str.length()-1][exp.length()-1]=true;
}
}
for(int j=exp.length()-2;j>=0;j=j-2) {//初始化最后一行
if(exp.charAt(j+1)=='*') {//
dp[str.length()][j]=true;
}
else {
break;
}
}
}
}
posted on 2019-05-15 22:06 coding_gaga 阅读(352) 评论(0) 编辑 收藏 举报