[程序员代码面试指南]字符串问题-字符串匹配问题(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;
}
}
}
}
[程序员代码面试指南]字符串问题-字符串匹配问题(DP)的更多相关文章
- [程序员代码面试指南]字符串问题-回文最少分割数(DP)
问题描述 给定一个字符串,输出把它全部切成回文子串的最小分割数. 例:str="ACDCDCDAD",输出2. 解题思路 DP 存储结构 dp数组dp[len+1],dp[i]表示 ...
- [程序员代码面试指南]最长递增子序列(二分,DP)
题目 例:arr=[2,1,5,3,6,4,8,9,7] ,最长递增子序列为1,3,4,8,9 题解 step1:找最长连续子序列长度 dp[]存以arr[i]结尾的情况下,arr[0..i]中的最长 ...
- 程序员代码面试指南 IT名企算法与数据结构题目最优解
原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...
- 程序员代码面试指南:IT名企算法与数据结构题目最优解
第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...
- [程序员代码面试指南]递归和动态规划-数字字符串转换为字母组合的种数(DP)
题意 给一个字符串,只由数字组成,若是'1'-'26',则认为可以转换为'a'-'z'对应的字母,问有多少种转换方法. 题解 状态转移很好想,注意dp多开一位,dp[0]为dp[2]的计算做准备.dp ...
- 《程序员代码面试指南》第五章 字符串问题 去掉字符串中连续出现k 个0 的子串
题目 去掉字符串中连续出现k 个0 的子串 java代码 package com.lizhouwei.chapter5; /** * @Description: 去掉字符串中连续出现k 个0 的子串 ...
- [程序员代码面试指南]递归和动态规划-最长公共子串问题(DP,LCST)
问题描述 如题. 例:输入两个字符串 str1="1AB234",str2="1234EF" ,应输出最长公共子串"234". 解题思路 状 ...
- 《程序员代码面试指南》第三章 二叉树问题 判断t1 树中是否有与t2 树拓扑结构完全相同的子树
题目 判断t1 树中是否有与t2 树拓扑结构完全相同的子树 java代码 package com.lizhouwei.chapter3; /** * @Description: 判断t1 树中是否有与 ...
- [程序员代码面试指南]递归和动态规划-最小编辑代价(DP)
问题描述 输入 原字符串StrOrg,目标字符串StrTarget,插入.删除.替换的编辑代价ic,dc,rc.输出将原字符串编辑成目标字符串的最小代价. 解题思路 状态表示 dp[i][j]表示把s ...
随机推荐
- CPF 入门教程 - 数据绑定和命令绑定(二)
CPF netcore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) 数据绑定和Wpf类似,支持双向绑定.数据绑定和命令绑定是UI和业务逻辑分离的基础 ...
- Elasticsearch第五篇:PlainElastic.Net 操作 Elasticsearch
再次强调,我安装的Elasticsearch 版本是 7.8.0 ,C# 操作 Elasticsearch 的驱动有 NEST.Elasticsearch.net .PlainElastic.Net ...
- Android Failed to find layer (XXX/XXX.xxActivity#0) in layer parent (no-parent).
报错: Failed to find layer (XXX/XXX.xxActivity#0) in layer parent (no-parent). 解决: 将该xxActivity复制一份到桌面 ...
- SpringSecurity权限管理系统实战—七、处理一些问题
目录 SpringSecurity权限管理系统实战-一.项目简介和开发环境准备 SpringSecurity权限管理系统实战-二.日志.接口文档等实现 SpringSecurity权限管理系统实战-三 ...
- Nginx学习简记_part2
第4章:nginx配置实例 -反向代理 4.1 反向代理实例一 实现效果:使用 nginx 反向代理,访问 www.123.com 直接跳转到 127.0.0.1:8080 4.1.1 实验代码 1) ...
- libview关于图片导入并显示
1 程序框图->图形与声音->图形格式,选择“写入某个格式的图片”,然后在路径处创建输入控件,然后在“图片函数”中选择“绘制平面像素图”,在控件输出端“新图片”创建显示控件.打开前面板,在 ...
- CSS动画实例:小圆球的海洋
CSS背景属性用于定义HTML元素的背景,在CSS提供的背景属性中, background-image:指定要使用的一个或多个背景图像: background-color:指定要使用的背景颜色: ba ...
- Javascript基本数据认识
1.Js的组成 2.Js的三种引入 行内式 <input type="button" value="来嘛来嘛" onclick="alert(' ...
- express-session中的saveUninitialized和resave
app.use(session({ name: config.session.name, secret: config.session.secret, resave: true, saveUninit ...
- Mybatis入门篇之基础CRUD
前言 作为一个资深后端码农天天都要和数据库打交道,最早使用的是 Hiberate,一个封装性极强的持久性框架.自从接触到 Mybatis 就被它的灵活性所折服了,可以自己写 SQL,虽然轻量级,但是麻 ...