程序源代码:点击打开链接

1.引入

字符串模式匹配。首先我们引入目标串,模式串的概念,而字符串模式匹配就是查找模式串在目标串中的位置。

2.brute-Force算法

brute-Force算法,我的理解是这样的。首先设目标串target="t0t1t2t3t4",pattern="p0p1p2"。将p0与t0比较,若相同,则继续比较p1与t1。若不同,则从t1与p0开始比较。下面我们举个例子:

target="aababcd",pattern="abcd";用target[i],pattern[j]分别表示target与pattern对应位置的字符(i,j初始为0)。

首先target[i]的a与pattern[j]的a相同,于是i++,j++。此时target[i]的a与pattern[j]的b不同,于是i=i-j+1,j=0。比较target[i]的a与pattern[j]的a相同,于是i++,j++。此时target[i]的b与pattern[j]的b相同,于是i++,j++。此时target[i]的a与pattern[j]的c不相同,于是i=i-j+1,j=0。此时target[i]的b与pattern[j]的a不相同,于是i++,j=0。此时target[i]的a与pattern[j]的a相同,于是i++,j++。此时,target[i]的b与pattern[j]的b相同,于是i++,j++。此时target[i]的c与pattern[j]的c相同,于是i++,j++。此时target[i]的d与pattern的d相同,于是i++,j++。测试j=pattern.length=4,表示在目标串target中找到了模式串pattern,于是返回模式串在目标串中的位置3。

下面是Brute-Force算法描述:

设目标串中的字符为ti(0<=i<n),模式串中的字符为pj(0<=0<m,m<=n),将他们比较:

(1)若ti=pj,继续比较ti+1与pj+1,直到j=m,则“ti-m+1……ti”与“p0……pm-1”匹配成功,返回模式串在目标串中匹配子串序号i-m+1。

(2)若ti!=pj,表示“ti-j…ti…ti-j+m-1”与“p0…pj…pm-1”匹配失败;目标串下一个匹配子串是“ti-j+1…ti-j+m”,继续比较ti-j+1与p0。此时,目标串回溯,从ti退回ti-j+1。

   程序流程图如下:

代码如下:

/*** * @author 冯利* @version 创建时间:2018年5月18日 上午9:51:20*/
public class MyStringMatch {/*** 从目标串的begin开始,查找模式串pattern在目标串中的位置* * @auther 冯利* @version 创建时间:2018年5月18日 上午9:51:08* @param pattern* @param begin* @return*/public static int indexOf(String target, String pattern, int begin) {// i为目标串target的索引int i = begin;// j为模式串pattern的索引int j = 0;// 输入要求if (target == null || target.equals("") || pattern == null || pattern.equals("") || begin > target.length()) {return -1;}// 循环,直到target或pattern被遍历完do {if (target.charAt(i) == pattern.charAt(j)) {i++;j++;} else {i = i - j + 1;j = 0;}} while (i < target.length() && j < pattern.length());// 模式串是否存在于目标串if (j == pattern.length()) {return i - pattern.length() ;}return -1;}
}   

测试代码如下:

public static void main(String[] args){System.out.println(MyStringMatch.indexOf("aababcd", "cd", 0));}

运行结果如下:

3.KMP算法

由于暴力匹配算法目标串存在回溯,有缺陷,因此引入了Kmp这种不存在回溯的算法。而这个算法的核心是找出模式串中相同的最长前缀子串和后缀子串的长度k。Kmp算法如下:

KMP算法与brute-Force算法的区别,在于当ti!=pj时,brute-Force算法要回溯,也就是i=i-j+1,j=0;而KMP算法将从ti与pk进行比较。所以求k是关键,接下来我们介绍求k的算法。

首先,我们需要一个数组next来存模式串中每个字符(假设匹配时在这里出错)的k。举例:模式串“abcabc”的next数组

KMP算法充分利用前一次的比较结果,由next[j]逐个递推计算得到next[j+1]。下面是一些说明:

(1)约定next[0]=-1,-1表示下次匹配从tj+1与p0开始比较;约定next[1]=0,表示下次匹配从tj与p0开始比较。

(2)对模式串当前字符序号j(0<=j<m),设next[j]=k,表示在“p0……pj-1”串中存在长度为k的相同的前缀子串和后缀子串,即“p0……pk-1”="pj-k……pj-1",0<=k<j且k取最大值。

(3)对next[j+1]而言,求“p0……pj-1pj”中相同前后子串的长度k,需要比较前缀子串“p0……pk-1”与后缀子串“pj-k+1……pj”是否匹配。

说明说完了,计算next数组的真正方法:假设target与pattern在ti于pj+1处匹配失败(即ti!=pj+1),并且已知“p0……pk-1”=“pj-k……pj-1”(也就是next[j]=k),此时只需要比较pk与pj是否相同。

1.如果pk=pj,或k=-1时则next[j+1]=k+1=next[j]+1.

2.如果pk!=pj,则在“p0……pj”串中寻找较短的相同前后缀子串(即令k=next[k],再比较pj与pk)。

下面举个例子,求模式串“abcabdabcabcaa”的next数组

当在j=12时匹配失败,则比较p11与p5(k=next[11]=5)。此时p11!=p5,于是k=next[5]=2。此时比较p11与p2,相等,于是next[j+1]=2+1=3。

求next的流程图如下:

至此,kmp的求next算法已经有了。这儿有一个改进了的求next数组的方法。下面介绍。

    当ti!=pj时,next[j]=k,若pk=pj,可知ti!=pk,则下次模式匹配串从pnext[k]开始比较。显然next[k]<next[j]越小,next[j]越小,模式串右移的距离越远,比较的次数也越少。下面举两个例子。

模式串“abcabc”的next数组

模式串“abcabdabcabcaa”的next数组

改进了的求next流程图如下:

kmp代码如下:

/*** kmp模式匹配算法* * @auther 冯利* @version 创建时间:2018年5月18日 下午9:38:43* @param target*            目标串* @param pattern*            模式串* @param begin*            从目标串中起始匹配位置* @return -1:表示匹配失败;其他表示pattern在target中的位置*/public static int indexOf_KMP(String target, String pattern, int begin) {//未改进的next求法//int next[] = getNextW(pattern);//改进了的next求法int next[]=getNext(pattern);// i为目标串target的索引int i = begin;// j为模式串pattern的索引int j = 0;// 输入要求if (target == null || target.equals("") || pattern == null || pattern.equals("") || begin > target.length()) {return -1;}// 循环,直到target或pattern被遍历完do {if (target.charAt(i) == pattern.charAt(j)) {i++;j++;} else {j = next[j];if (j == -1) {i++;j++;}}} while (i < target.length() && j < pattern.length());// 模式串是否存在于目标串if (j == pattern.length()) {return i - pattern.length();}return -1;}/*** 未改进的求next方法* @auther 冯利* @version 创建时间:2018年5月18日 下午9:45:59* @param pattern*            模式串* @return*/private static int[] getNextW(String pattern) {int next[] = new int[pattern.length()];next[0] = -1;int j = 1;while (j < pattern.length()) {int k = next[j - 1];while (true) {if (k == -1 || pattern.charAt(j-1) == pattern.charAt(k)) {next[j] = k + 1;break;} else {k = next[k];}}j++;}return next;}/*** 改进了的求next方法* @auther 冯利* @version 创建时间:2018年5月18日 下午9:45:59* @param pattern*            模式串* @return*/private static int[] getNext(String pattern) {int next[] = new int[pattern.length()];next[0] = -1;int j = 1;while (j < pattern.length()) {int k = next[j - 1];while (true) {if (k == -1 || pattern.charAt(j-1) == pattern.charAt(k)) {next[j] = k + 1;break;} else {k = next[k];}}if(pattern.charAt(j)==pattern.charAt(next[j])){next[j]=next[next[j]];}j++;}return next;}

测试代码:

/*** * @author 冯利* @version 创建时间:2018年5月18日 上午10:01:20*/
public class Main {public static void main(String[] args){System.out.println(MyStringMatch.indexOf_Force("aababcd", "cd", 0));System.out.println(MyStringMatch.indexOf_Force("abcdabcabbabcabc", "abcabc", 0));System.out.println(MyStringMatch.indexOf_KMP("aababcd", "cd", 0));System.out.println(MyStringMatch.indexOf_KMP("abcdabcabbabcabc", "abcabc", 0));}
}

运行结果:

程序源码:点击打开链接

    

数据结构之字符串模式匹配相关推荐

  1. 数据结构---BF字符串模式匹配

    数据结构-BF字符串模式匹配 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> int BF(char * S, cha ...

  2. 字符串模式匹配--KMP之美

    字符串模式匹配: 给定字符串,要求在该字符串(主串)中找到所有匹配一个模式串的子串(一般是返回子串在字符串中的开头位置).这里把问题简化一下--在该字符串中找到第一个匹配对应模式串的子串即可.要找出剩 ...

  3. KMP字符串模式匹配详解

    KMP字符串模式匹配详解 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度为O(m+n).. 一 ...

  4. 深入剖析Redis系列(五) - Redis数据结构之字符串

    前言 字符串类型 是 Redis 最基础的数据结构.字符串类型 的值实际可以是 字符串(简单 和 复杂 的字符串,例如 JSON.XML).数字(整数.浮点数),甚至是 二进制(图片.音频.视频),但 ...

  5. 数据结构——基于字符串模式匹配算法的病毒感染检测

    实验四 基于字符串模式匹配算法的病毒感染检测 [实验目的] 1.掌握字符串的顺序存储表示方法. 2.掌握字符串模式匹配BF算法和KMP算法的实现. [实验内容] 问题描述 医学研究者最近发现了某些新病 ...

  6. lisp 提取字符串中的數字_Redis 数据结构之字符串的那些骚操作

    Redis 字符串底层用的是 sds 结构,该结构同 c 语言的字符串相比,其优点是可以节省内存分配的次数,还可以... 这样写是不是读起来很无聊?这些都是别人咀嚼过后,经过一轮两轮三轮的再次咀嚼,吐 ...

  7. 【算法视频】字符串模式匹配--布鲁特.福斯算法

    2.4.字符串模式匹配 资讯网址:www.qghkt.com 腾讯课堂:https://qghkt.ke.qq.com/20个常用算法 模式串(或子串)在主串中的定位操作通常称为串的模式匹配,它是各种 ...

  8. 算法笔记:简单的字符串模式匹配-BF算法

    字符串模式匹配是匹配字符串A中是否存在子串a,一般字符串的结尾为'\0',可以以此作为字符串结束的判定标准. 其过程原理图如下所示: 给出源代码: #include<stdio.h> #i ...

  9. KMP算法字符串模式匹配

    KMP字符串模式匹配详解 来自CSDN     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算 ...

最新文章

  1. 轻松了解Kubernetes认证功能
  2. Oracle 9i 从9.2.0.1升级到 9.2.0.6 步骤
  3. wxWidgets:wxAUI 概述
  4. c++之静态成员详细介绍
  5. 数据结构与算法 | 直接选择排序、双向选择排序
  6. 金融模型python_盘点金融领域里常用的深度学习模型
  7. 安装phpssdb扩展:
  8. RocketMQ避坑指南:springcloud教程权威指南
  9. bbb u-boot mmc总线初始化分析
  10. 副法线和正切是什么?
  11. 【8.12测试】辉夜的见面礼
  12. C# .NET与数据结构
  13. 为什么我不再推荐使用MVC框架?
  14. keil4和烧录软件的基本使用
  15. JS实现俄罗斯方块小游戏
  16. Tiktok shop小店注册以及如何一键上传产品批量上货铺货
  17. Layer 开启与关闭加载层
  18. 大国崛起(三) 大不列颠及北爱尔兰联合王国(英国)
  19. 实践练习二(必选):手动部署 OceanBase 单副本集群
  20. 铁打的阿里,流水的美团,21届校招生Offer薪资曝光后,伤了老员工的心…

热门文章

  1. Corel MyDVD Pro for Mac(专业DVD制作软件)
  2. Python可以解决哪些生活中的小问题
  3. C/C++实现你的浪漫表白:浪漫流星雨表白程序
  4. android 双触摸屏(touchscreen)实现--kernel driver
  5. 使用AmazeUI做的一个表单案例(验证)
  6. 【Pytorch项目实战】之生成式模型:DeepDream、风格迁移、图像修复
  7. 蓝色3D风格软件系统后台登录PSD模板
  8. python学习之pip的安装与使用
  9. parallel desktop 16.5安装windows10和linux(MacBook Pro M1版)
  10. 数学-那些伟大的数学家01-数学家纪年表