问题描述

  • 字符串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. Ng-Matero V10 正式发布!

    Angular v10 在六月下旬就悄无声息的发布了,虽然 v9 的发布延期了两个月,但是 v10 并没有受影响,仍然如期而至. 相比 v9 的重量级发布,v10 并没有颠覆性的变化,主要还是 bug ...

  2. JavaScript正则表达式的模式匹配教程,并且附带充足的实战代码

    JavaScript正则表达式的模式匹配 引言 正文 一.正则表达式定义 二.正则表达式的使用 三.RegExp直接量 (1)正则表达式初体验 (2)深入了解正则 字符类 重复 选择 分组与引用 指定 ...

  3. servlet的生命周期和工作原理介绍

    一.servlet生命周期 Servlet生命周期分为三个阶段: 1)初始化阶段: 调用init()方法 2)响应客户请求阶段:调用service()方法 3)终止阶段:调用destroy()方法 T ...

  4. 随机陷阱和P值

    如果让大家写一个50次的抛硬币实验的可能结果(头像H或字T),多半人在连续三个一样的后,会换一下.因为大家都知道,连续一样的越多,概率越小,越不可能发生.大部分人不会去想,其实HHHTT和HHHHH发 ...

  5. CVE-2020-15778 OpenSSH命令注入漏洞复现

    一.漏洞概要 OpenSSH 8.3p1及之前版本中的scp允许在scp.c远程功能中注入命令,攻击者可利用该漏洞执行任意命令.目前绝大多数linux系统受影响. 参考链接:https://githu ...

  6. 正则表达式截取xml

    $str = '<Ips><GateWayRsp><head><ReferenceID>123</ReferenceID><RspCo ...

  7. aarch64 packages 地址链接收集

    1.http://dl.fedoraproject.org/pub/epel/7/aarch64 2.https://rpmfind.net/linux/epel/7/aarch64/ 3.http: ...

  8. 华为云配置Objected-based Storage System

    本实验要求基于开源的对象文件系统(例如Ceph),搭建视频点播(VoD)网站.可参考使用Ceph, wordpress, php 以及nginx 实现相关功能,主要包含以下方面: 配置Ceph; 配置 ...

  9. 还在问什么是JavaScript构造函数、实例、原型对象以及原型链?看完这篇你就懂

    1概述 ES6, 全称 ECMAScript 6.0 ,2015.06 发版.在ES6之前,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征. 2构造函数 构造函数是一种特 ...

  10. .Net MongoDB批量修改集合中子集合的字段

    环境:.Net Core 3.1 (需要导入.Net MongoDB的驱动) 模型 /// <summary> /// 收藏 /// </summary> public cla ...