【Offer】[19] 【字符串匹配】
题目描述
请实现一个函数用来匹配包括'.'
和'*'
的正则表达式。 模式中的字符'.'表示任意一个字符,而'*'
表示它前面的字符可以出现任意次(包含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。 例如,字符串"aaa"
与模式"a.a"
和"ab*ac*a"
匹配,但是与"aa.a"
和"ab*a"
均不匹配
思路分析
使用递归函数 matchCore(char[] str, int i, char[] pattern, int j)
来比较索引i,j
位置上的字符是否匹配,大体分为两种情况:
- 当前字符的下一个字符不是
*
时,如果当前字符相等,则继续调用函数比较下一字符,i
和j
索引都+1
,不相等则返回false
- 当前字符的下一个字符是
*
时,如果当前字符不相等,这时将模式串索引j+2(跳过a*
),继续比较;如果相等:- 字符串的索引i+1,匹配串索引j+2
- 字符串的索引i+1,匹配串索引不变
- 字符串的索引不变,匹配串索引j+2 (例如
ba*ac
) 可以跳过a*
测试用例
- 功能测试(模式中包含普通字符、“.”、“*”;匹配情况;不匹配情况)
- 特殊测试(null,空字符串)
Java代码
public class Offer19 {
public static void main(String[] args) {
test1();
test2();
}
public static boolean match(char[] str, char[] pattern) {
return Solution1(str, pattern);
}
/**
* 方法1
* @param str 字符串
* @param pattern 模式串
* @return
*/
private static boolean Solution1(char[] str, char[] pattern) {
if(str == null || pattern == null) {
return false;
}
return matchCore(str,0,pattern, 0);
}
/**
* 字符串匹配的核心算法:
*
* @param str 字符串
* @param i 字符串当前索引
* @param pattern 模式串
* @param j 模式串当前索引
* @return
*/
private static boolean matchCore(char[] str, int i, char[] pattern, int j) {
if(i==str.length && j==pattern.length) {
return true;
}
if(i<str.length && j==pattern.length) {
return false;
}
if(j+1<pattern.length && pattern[j+1] == '*') {
if((i<str.length && (str[i] == pattern[j]) || pattern[j]=='.')) {
//这里需要判断字符串和匹配串当前字符是否相等, 如果模式串当前字符为'.',也为相等
return matchCore(str,i+1,pattern,j+2)
|| matchCore(str, i+1, pattern, j)
|| matchCore(str, i, pattern, j+2); // 如果模式串是 ba*ac这种情况 a*是可以直接跳过的
}else {
return matchCore(str,i,pattern,j+2); // 当前字符不相等,可以直接跳过a*
}
}
//这里要放在后面
if(i<str.length && (str[i]==pattern[j] || pattern[j]=='.')) {
return matchCore(str, i+1, pattern, j+1);
}
return false;
}
/**
* 此测试程序参考自 剑指Offer一书中的源码[https://github.com/zhedahht/CodingInterviewChinese2]
* @param testName
* @param str
* @param pattern
* @param expected
*/
private static void test(String testName, char[] str, char[] pattern, boolean expected) {
System.out.print(testName + ":");
if (match(str, pattern) == expected)
System.out.println("passed!");
else
System.out.println("failed!");
}
/**
* 功能测试
*/
private static void test1() {
char[] str1 = "aaa".toCharArray();
char[] str2 = "aaa".toCharArray();
char[] pattern1 = "a*.b*b*aa".toCharArray();
char[] pattern2 ="ab*ac*a".toCharArray();
test("aaa,a*.b*b*aa --->", str1, pattern1, true);
test("aaa,ab*ac*a--->", str2, pattern2, true);
char[] str3 = {'a'};
char[] pattern3 = {'.','*'};
test("a, .* -->", str3, pattern3, true);
}
/**
* 特殊测试
*/
private static void test2() {
char[] str = {};
char[] pattern = null;
test("{},null --->", str, pattern, false);
}
}
代码链接
【Offer】[19] 【字符串匹配】的更多相关文章
- 剑指 Offer 19. 正则表达式匹配 + 动态规划
剑指 Offer 19. 正则表达式匹配 题目链接 一. 字符串匹配大致可以分为三种情况: 第一种:正则串的最后一个字符为正常字符,此时根据主串的最后一个字符是否和它相同来判断是否匹配, 如果相同,则 ...
- 字符串匹配--Karp-Rabin算法
主要特征 1.使用hash函数 2.预处理阶段时间复杂度O(m),常量空间 3.查找阶段时间复杂度O(mn) 4.期望运行时间:O(n+m) 本文地址:http://www.cnblogs.com/a ...
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- 【Java编程】Java中的字符串匹配
在Java中,字符串的匹配可以使用下面两种方法: 1.使用正则表达式判断字符串匹配 2.使用Pattern类和Matcher类判断字符串匹配 正则表达式的字符串匹配: ...
- "《算法导论》之‘字符串’":字符串匹配
本文主要叙述用于字符串匹配的KMP算法. 阮一峰的博文“字符串匹配的KMP算法"将该算法讲述得非常形象,可参考之. 字符串‘部分匹配值’计算 KMP算法重要的一步在于部分匹配值的计算.模仿& ...
- 字符串匹配的KMP算法
~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...
- {Reship}{KMP字符串匹配}
关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827
- 字符串匹配(hash算法)
hash函数对大家来说不陌生吧 ? 而这次我们就用hash函数来实现字符串匹配. 首先我们会想一下二进制数. 对于任意一个二进制数,我们将它化为10进制的数的方法如下(以二进制数1101101为例): ...
- 【C++实现python字符串函数库】二:字符串匹配函数startswith与endswith
[C++实现python字符串函数库]字符串匹配函数startswith与endswith 这两个函数用于匹配字符串的开头或末尾,判断是否包含另一个字符串,它们返回bool值.startswith() ...
随机推荐
- bucket list 函数解析
cls_bucket_list 函数 librados::IoCtx index_ctx; // key - oid (for different shards if there is any) ...
- 【精选】Markdown 语法汇总
博客园也能Markdown?美滋滋,Markdown真的是好用QAQ. 本文档按照Markdown各种常用语法类别,以文字描述+演示的方式来展现markdown语法的使用.Markdown 的目标是实 ...
- Storm初识(1)
在Storm集群中,有两类节点:主节点 master node 和工作节点 worker nodes. 主节点运行着一个叫做Nimbus的守护进程.这个守护进程负责在集群中分发代码,为工作节点分配任务 ...
- [转载]关于ActiveMQ集群
转载于 http://blog.csdn.net/nimmy/article/details/6247289 近日因工作关系,在研究JMS,使用ActiveMQ作为提供者,考虑到消息的重要,拟采用Ac ...
- 欢迎加入我的知识星球:C语言解惑课堂
我在知识星球上开通了一个有关C语言基础答疑解惑的星球,它叫做:“C语言解惑课堂”.看这名字你就知道虽然有点俗,俗才贴近你的真正需求嘛!这是一个专门帮助C语言初学者答疑解惑的课堂.嗯~~~,关于这个星球 ...
- java算法(4)---静态内部类实现雪花算法
静态内部类单例模式实现雪花算法 在生成表主键ID时,我们可以考虑主键自增 或者 UUID,但它们都有很明显的缺点 主键自增:1.自增ID容易被爬虫遍历数据.2.分表分库会有ID冲突. UUID: 1. ...
- SIMBOSS:物联网业务如何应用领域驱动设计?
前言 在这个万物互联的时代,物联网业务蓬勃发展,但也瞬息万变,对于开发人员来说,这是一种挑战,但也是一种“折磨”. 在业务发展初期,因为时间有限,我们一般会遵循“小步快跑,迭代试错”的原则进行业务开发 ...
- testng学习笔记-- 场景和module
一.定义 TestNG是一个测试框架,其灵感来自JUnit和NUnit,但引入了一些新的功能,使其功能更强大,使用更方便. TestNG是一个开源自动化测试框架;TestNG表示下一代(Next Ge ...
- gin+vue的前后端分离开源项目
该项目是gin+vue的前后端分离项目,使用gorm访问MySQL,其中vue前端是使用vue-element-admin框架简单实现的: go后台使用jwt,对API接口进行权限控制.此外,Web页 ...
- Spring-Boot:拦截器注解范例
package com.example.aop; import java.lang.annotation.Documented; import java.lang.annotation.Element ...