这两天复习数据结构(严蔚敏版),记录第四章串中的两个重要算法,BF算法和KMP算法,博主主要学习Java,所以分析采用Java语言,后面会补上C语言的实现过程。


1、Brute-Force算法(暴力法)

要求:将主串的第i个字符(一般情况i为1)和字串的第一个字符进行比较。若相等,则继续比较后续字符;若不相等,则从主串的下一个字符起,重新与子串的第一个字符比较。成功,返回主串中与子串相匹配的子序列的第一个字符的序号;失败,返回0

public class Brute_Force {
/**
* 暴力法 ,O(m*n) (m、n分别为主串长度和子串长度)
* @param S 主串(原始字符串)
* @param T 子串(模式字符串)
* @return 如果模式字符串在原始字符串中存在,返回模式字符串在原始字符串中第一次出现的索引
*/
private int Index_BF(String S, String T) {
//习惯性排除错误的模式
if (S==null || S.length()<=0 || T==null || T.length()<=0)
return 0; int S_length = S.length();
int T_length = T.length();
int i=0, j=0;
while (i<S_length && j<T_length) {
if (S.charAt(i) == T.charAt(j)) {
i++;
j++;
}else {
//不等
i = i-j+1; //这一步的思想是主串返回到的步数为子串移动的步数i-j,然后从下一个开始+1
j = 0; //j返回索引为0的位置
}
}
if (j == T_length) {
return i-T_length;
}
return 0;
} //主方法,测试
public static void main(String[] args) {
Brute_Force bf = new Brute_Force();
String S = "hello world";
String T = "world";
System.out.println(bf.Index_BF(S,T)); //6
}
}

2、KMP算法

要求效果同上,只是更合理地应用部分已经匹配的结果

public class KMP {
/**
* KMP 高效法 ,O(m+n) (m、n分别为主串长度和子串长度)
* @param S 主串(原始字符串)
* @param T 子串(模式字符串)
* @return 如果模式字符串在原始字符串中存在,返回模式字符串在原始字符串中第一次出现的索引
*/
private int Index_KMP(String S, String T) {
//习惯性排除错误的模式
if (S==null || S.length()<=0 || T==null || T.length()<=0)
return 0; //得到子串的next数组
int[] nextArr = getNextArray(T);
int S_length = S.length();
int T_length = T.length();
int i=0, j=0;
while (i<S_length && j<T_length) {
if (j==-1 || S.charAt(i) == T.charAt(j)) {//j==-1第一个字符就和当前测试的字符不相等
i++;
j++;
}else {
j = nextArr[j];
}
}
if (j==T_length) {
return i-T_length;
}
return 0;
} /**
* 获取模式字符串的next数组
* @param str 子串
* @return
*/
private int[] getNextArray(String str) {
//习惯性排除错误的模式
if (str==null || str.length()<=0)
return null; int length = str.length();
int[] nextArr = new int[length];
int j=0, k=-1;
nextArr[0] = -1;
while (j<length-1) {
if (k==-1 || str.charAt(j) == str.charAt(k)) {
j++;
k++;
nextArr[j] = k;
}else {
k = nextArr[k];
}
}
return nextArr;
} //主方法,测试
public static void main(String[] args) {
KMP kmp = new KMP();
String S = "hello world";
String T = "world";
System.out.println(kmp.Index_KMP(S,T)); //6
}
}

3、KMP的讲解

KMP算法的核心,通俗来讲是,当S[i]和T[j]发生不匹配现象时,i指针不需要回溯,只需j指针回溯即可。详情可以看下这篇知乎:

https://www.zhihu.com/question/21923021/answer/281346746

大体的对比:

4、C语言实现

考试还是要用C语言,还是得好好参考下

BF算法:

#include <stdio.h>
#include <string.h>
//串普通模式匹配算法的实现函数,其中 B是主串,A是子串
int BF(char * B,char *A){
int i=0,j=0;
while (i<strlen(B) && j<strlen(A)) {
if (B[i]==A[j]) {
i++;
j++;
}else{
i=i-j+1;
j=0;
}
}
//跳出循环有两种可能,i=strlen(B)说明已经遍历完主串,匹配失败;j=strlen(A),说明子串遍历完成,在主串中成功匹配
if (j==strlen(A)) {
return i-strlen(A)+1;
}
//运行到此,为i==strlen(B)的情况
return 0;
}
int main() {
int number = BF("hello world", "world");
printf("%d",number);
return 0;
}

KMP算法:

#include <stdio.h>
#include <string.h>
void Next(char*T,int *next){
int i=1;
next[1]=0;
int j=0;
while (i<strlen(T)) {
if (j==0||T[i-1]==T[j-1]) {
i++;
j++;
next[i]=j;
}else{
j=next[j];
}
}
}
int KMP(char * S,char * T){
int next[10];
Next(T,next);//根据模式串T,初始化next数组
int i=1;
int j=1;
while (i<=strlen(S)&&j<=strlen(T)) {
//j==0:代表模式串的第一个字符就和当前测试的字符不相等;S[i-1]==T[j-1],如果对应位置字符相等,两种情况下,指向当前测试的两个指针下标i和j都向后移
if (j==0 || S[i-1]==T[j-1]) {
i++;
j++;
}
else{
j=next[j];//如果测试的两个字符不相等,i不动,j变为当前测试字符串的next值
}
}
if (j>strlen(T)) {//如果条件为真,说明匹配成功
return i-(int)strlen(T);
}
return -1;
} int main() {
int i=KMP("hello world","world");
printf("%d",i);
return 0;
}

BF算法和KMP算法的更多相关文章

  1. 字符串匹配-BF算法和KMP算法

    声明:图片及内容基于https://www.bilibili.com/video/av95949609 BF算法 原理分析 Brute Force 暴力算法 用来在主串中查找模式串是否存以及出现位置 ...

  2. 字符串匹配的BF算法和KMP算法学习

    引言:关于字符串 字符串(string):是由0或多个字符组成的有限序列.一般写作`s = "123456..."`.s这里是主串,其中的一部分就是子串. 其实,对于字符串大小关系 ...

  3. 串的模式匹配 BF算法和KMP算法

    设有主串s和子串t,子串t的定位就是要在主串中找到一个与子串t相等的子串.通常把主串s称为目标串,把子串t称为模式串,因此定位也称为模式匹配. 模式匹配成功是指在目标串s中找到一个模式串t: 不成功则 ...

  4. 串匹配模式中的BF算法和KMP算法

    考研的专业课以及找工作的笔试题,对于串匹配模式都会有一定的考察,写这篇博客的目的在于进行知识的回顾与复习,方便遇见类似的题目不会纠结太多. 传统的BF算法 传统算法讲的是串与串依次一对一的比较,举例设 ...

  5. BF算法和KMP算法 python实现

    BF算法 def Index(s1,s2,pos = 0): """ BF算法 """ i = pos j = 0 while(i < ...

  6. 字符串匹配(BF算法和KMP算法及改进KMP算法)

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include<cstring> ...

  7. BF算法和KMP算法(javascript版本)

    var str="abcbababcbababcbababcabcbaba";//主串 var ts="bcabcbaba";//子串 function BF( ...

  8. 数据结构(十六)模式匹配算法--Brute Force算法和KMP算法

    一.模式匹配 串的查找定位操作(也称为串的模式匹配操作)指的是在当前串(主串)中寻找子串(模式串)的过程.若在主串中找到了一个和模式串相同的子串,则查找成功:若在主串中找不到与模式串相同的子串,则查找 ...

  9. 软件设计师_朴素模式匹配算法和KMP算法

    1.从主字符串中匹配模式字符串(暴力匹配) 2. KMP算法

随机推荐

  1. Selenium系列4-元素定位

    前言 说起元素定位,一定是学习自动化测试绕不开的第一道关,无论是web端的UI自动化还是移动端的自动化,在需要首先对元素进行定位才可以完成对元素的操作已达成测试目的,在Selenium中,可以使用fi ...

  2. PHP的变量赋值

    这个标题估计很多人会不屑一顾,变量赋值?excuse me?我们学开发的第一课就会了好不好.但是,就是这样基础的东西,反而会让很多人蒙圈,比如,值和引用的关系.今天,我们就来具体讲讲. 首先,定义变量 ...

  3. vue跳转路由

    1.  router-link 1. 不带参数 <router-link :to="{name:'home'}"> <router-link :to=" ...

  4. 显式等待until传入自定义方法

    WebDriverWait(driver,10).until(expected_conditions.element_to_be_clickable(ele)) 通过追踪代码,可以发现上面的eleme ...

  5. 关于微信小程序爬虫关于token自动更新问题

    现在很多的app都很喜欢在微信或者支付宝的小程序内做开发,毕竟比较方便.安全.有流量.不需要再次下载app,好多人会因为加入你让他下载app他会扭头就走不用你的app,毕竟做类似产品的不是你一家. 之 ...

  6. 51nod1667-概率好题【容斥,组合数学】

    正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1667 题目大意 两个人. 第一个人有\(k_1\)个集合,第\(i\)个 ...

  7. RabbitMQ 3.9.7 镜像模式集群与Springboot 2.5.5 整合

    1. 概述 老话说的好:做人要懂得变通,善于思考,有时稍微转个弯,也许问题就解决了. 言归正传,之前我们聊了 RabbitMQ 3.9.7 镜像模式集群的搭建,今天我们来聊聊 RabbitMQ 3.9 ...

  8. Django整理(四) - URL配置

    1. URL配置 一.需求 1. 需求:在浏览器访问URL地址 http://127.0.0.1:8000/users/index 时,显示hello django信息 2. 实现 i. 需要编写一个 ...

  9. 多项目如何高效协同合作 | springcloud系列之bus消息总线

    前言 在springcloud config章节中我们完成了配种中心的搭建,以及通过配置中心完成配置的抽离通过springcloud config模块我们将配置抽离到git仓库中我们不必要每次为了改配 ...

  10. 100台机器上海量IP如何查找出现频率 Top 100?

    场景题 有 100 机器,每个机器的磁盘特别大,磁盘大小为 1T,但是内存大小只有 4G,现在每台机器上都产生了很多 ip 日志文件,每个文件假设有50G,那么如果计算出这 100 太机器上访问量最多 ...