问题描述

  • 字符串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. [noip2002] 产生数

    题目描述 给出一个整数 n (n<1030)和 k 个变换规则 (k < 15) . 规则: 一位数可变换成另一个一位数: 规则的右部不能为零. 例如:n = 234 .有规则( k=2  ...

  2. Linked server的一个问题

    好久没有写新的博客,主要是很久没有什么动力和需求来写程序.虽然也不是一点没写,但都缺乏技术含量,没什么可说的. 前两天碰到一个关于linked server的问题.本地的sql server里,通过l ...

  3. Scala的安装和配置

    1.Windows下搭建Scala开发环境 1)Scala需要Java运行时库,安装Scala需要首先安装JVM虚拟机并配置好,推荐安装JDK1.8 2)在http://www.scala-lang. ...

  4. 使用openpyxl创建excel,设置不显示网格线

    最近在学openpyxl,想设置excel不显示网格线,试了好多种方法都不行,最后发现可以通过修改views文件来实现. 文件路径:虚拟目录\Lib\site-packages\openpyxl\wo ...

  5. 浅谈Docker(一)

    注:由于别人写的太好了就转来基础介绍! 转自:http://www.infoq.com/cn/articles/docker-core-technology-preview Docker是PaaS供应 ...

  6. cinder-volume服务上报自己的状态给cinder-scheduler的rpc通信代码分析

    以juno版本为基础,主要从消息的生产者-消费者模型及rpc client/server模型来分析cinder-volume是如何跟cinder-scheduler服务进行rpc通信的 1.cinde ...

  7. python编程中的并发------多进程multiprocessing

    任务例子:喝水.吃饭动作需要耗时1S 单任务:(耗时20s) for i in range(10): print('a正在喝水') time.sleep(1) print('a正在吃饭') time. ...

  8. 区块链入门到实战(21)之以太坊(Ethereum) – 分布式应用(DApp)

    作用:用户交互 分布式应用(DApp)是运行在区块链之上的应用程序,支持区块链网络中用户之间的交互. DApp(decentralized application)的后端代码运行在区块链网络上,这个可 ...

  9. 软件工程第二次作业(Junit和GoogleTest)

    使用Eclipse的Junit框架进行单元测试 一.前言 我的电脑因为以前学过安卓开发,已经安装好了eclipse,看了邹欣老师的博客,博客上讲的的非常详细,所以在进行的过程中遇到困难,基本都能解决. ...

  10. Spring Security 入门学习--数据库认证和授权

    首先是使用的SpringBoot框架 基础需要的pom以来如下,基础的springboot项目的创建就不一一赘述了. <!--spring web--> <dependency> ...