问题描述

  • 字符串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;
}
}
}
}

[程序员代码面试指南]字符串问题-字符串匹配问题(DP)的更多相关文章

  1. [程序员代码面试指南]字符串问题-回文最少分割数(DP)

    问题描述 给定一个字符串,输出把它全部切成回文子串的最小分割数. 例:str="ACDCDCDAD",输出2. 解题思路 DP 存储结构 dp数组dp[len+1],dp[i]表示 ...

  2. [程序员代码面试指南]最长递增子序列(二分,DP)

    题目 例:arr=[2,1,5,3,6,4,8,9,7] ,最长递增子序列为1,3,4,8,9 题解 step1:找最长连续子序列长度 dp[]存以arr[i]结尾的情况下,arr[0..i]中的最长 ...

  3. 程序员代码面试指南 IT名企算法与数据结构题目最优解

    原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...

  4. 程序员代码面试指南:IT名企算法与数据结构题目最优解

      第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...

  5. [程序员代码面试指南]递归和动态规划-数字字符串转换为字母组合的种数(DP)

    题意 给一个字符串,只由数字组成,若是'1'-'26',则认为可以转换为'a'-'z'对应的字母,问有多少种转换方法. 题解 状态转移很好想,注意dp多开一位,dp[0]为dp[2]的计算做准备.dp ...

  6. 《程序员代码面试指南》第五章 字符串问题 去掉字符串中连续出现k 个0 的子串

    题目 去掉字符串中连续出现k 个0 的子串 java代码 package com.lizhouwei.chapter5; /** * @Description: 去掉字符串中连续出现k 个0 的子串 ...

  7. [程序员代码面试指南]递归和动态规划-最长公共子串问题(DP,LCST)

    问题描述 如题. 例:输入两个字符串 str1="1AB234",str2="1234EF" ,应输出最长公共子串"234". 解题思路 状 ...

  8. 《程序员代码面试指南》第三章 二叉树问题 判断t1 树中是否有与t2 树拓扑结构完全相同的子树

    题目 判断t1 树中是否有与t2 树拓扑结构完全相同的子树 java代码 package com.lizhouwei.chapter3; /** * @Description: 判断t1 树中是否有与 ...

  9. [程序员代码面试指南]递归和动态规划-最小编辑代价(DP)

    问题描述 输入 原字符串StrOrg,目标字符串StrTarget,插入.删除.替换的编辑代价ic,dc,rc.输出将原字符串编辑成目标字符串的最小代价. 解题思路 状态表示 dp[i][j]表示把s ...

随机推荐

  1. troubleshoot之:分析OutOfMemoryError异常

    目录 简介 OutOfMemoryError java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: GC Ov ...

  2. 图片降噪(Scipy)

    以登月图片为例,通过使用Scipy 傅立叶变换,实现图片消噪 scipy.fftpack模块用来计算快速傅里叶变换速度比传统傅里叶变换更快,是对之前算法的改进图片是二维数据,注意使用fftpack的二 ...

  3. python - 基础局部变量和全局变量

    python中全局变量和局部变量的最大区别在于局部变量只能通过函数去访问,而全局变量可以直接访问 首先我们来看下什么是全局变量和局部变量 全局变量:在函数之外定义的变量,所有函数内可以调用这个全局变量 ...

  4. JavaScript学习系列博客_29_JavaScript arguments

    arguments (封装实参的对象) 在调用函数时,浏览器每次都会传递进两个隐含的参数:1.函数的上下文对象 this2.封装实参的对象 arguments- arguments是一个类数组对象,它 ...

  5. 修改vsftpd的默认根目录/var/ftp/pub到另一个目录

    修改ftp的根目录只要修改/etc/vsftpd/vsftpd.conf文件即可: 加入如下几行: local_root=/var/www/html chroot_local_user=YES ano ...

  6. cenos 7 mysql

    CentOS 7的yum源中貌似没有正常安装mysql时的mysql-sever文件,需要去官网上下载 # wget http://dev.mysql.com/get/mysql-community- ...

  7. 牛客网数据库SQL实战解析(11-20题)

    牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...

  8. (数据科学学习手札94)QGIS+Conda+jupyter玩转Python GIS

    本文完整代码及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 QGIS随着近些年的发展,得益于其开源免费 ...

  9. GitBook 常用插件

    目录 必看说明 插件说明 page-treeview 目录 code 代码 pageview-count 阅读量计数 popup 图片点击查看 tbfed-pagefooter 页面添加页脚(简单版) ...

  10. vue项目中遇到的问题(包含兼容性问题)

    一.由于懒加载,使用elementUI里面的dialog的时候dialog还未被渲染成DOM元素,调用清空表单验证的方法会报错this.$refs[formName].resetFields(); 解 ...