暴力匹配算法和KMP算法

问题:如果有两个字符串str1,str2,我们要判断str2是否是str1的子字符串,我们可以采用暴力匹配算法,和KMP算法解决

1.暴力匹配算法

1.将两个字符串都变成字符数组;

        char []s1=str1.toCharArray();
        char []s2=str2.toCharArray();

2.判断s1[i]和s2[j]是否相等

(1.)不相等则i=i-j+1; j=0; 每次匹配失败s1的索引只往后移动一位
在这里插入图片描述

在这里插入图片描述
(2.)相等那么j++,i++
在这里插入图片描述

在这里插入图片描述
直到s1的空格和s2的D不匹配则进行(1)
在这里插入图片描述

在这里插入图片描述
完整java代码如下:

package com.yg.algorithm;/*
@author  Mu_Mu
@date    2020/3/18  9:27
*/

public class ViolenceMatch {
    public static void main(String[] args) {
    String str1="hahahahehehahe";
    String str2="hehehahe";
        System.out.println("index:"+violenceMath(str1,str2));
    }

    public static int violenceMath(String str1, String str2) {
        char []s1=str1.toCharArray();
        char []s2=str2.toCharArray();
        int s1Len=s1.length;
        int s2Len=s2.length;
        int i = 0;//s1的索引
        int j=0;//s2的索引
        while (i < s1Len && j < s2Len) {
            if (s1[i] == s2[j]) {
                i++;
                j++;
            } else {
                i = i - (j - 1);
                j=0;
            }
        }
        if (j == s2Len) {
            return i - j;
        } else {
            return -1;
        }

    }
}

2.KMP算法

1.建立一个部分匹配表:

部分匹配表:用一个一维数组next[]表示字符串中相同前缀后缀的最大长度,next[0]恒等于0;
next[j] = k 代表p[j] 之前的模式串子串中,有长度为k 的相同前缀和后缀

如字符串str=“A”;
它不能踩分为前缀和后缀所以它的部分匹配表为next:[0];

字符串str=“AA”;
它可以拆分为前缀A,和后缀A;
因为第二个A加进来后相同前缀和后缀的最大长度为1所以next[1]=1;

它的部分匹配表为 next:[0,1];

字符串str=“AAB”;
它可以拆分为前缀A,AA和后缀AB,B
因为B加进来后相同前缀和后缀的最大长度为0所以next[2]=0;

它的部分匹配表为 next:[0,1,0];

在KMP匹配中,当模式串中j 处的字符失配时,下一步用next[j]处的字符继续跟文本串匹配,相当于模式串向右移动j - next[j] 位。

构建部分匹配表

//获取到一个字符串(子串)的部分匹配表
    public static int[] kmpNext(String dest) {
        //创建一个next数组保存部分匹配值
        int[] next = new int[dest.length()];
        //当只有一个字符时匹配值为0
        next[0]=0;
        for (int i = 1, j = 0; i < dest.length(); i++) {

            while (j>0&&dest.charAt(i) != dest.charAt(j)) {
            //每次寻找部分匹配表j前面的一个匹配值
                j=next[j-1];
            }
            //字符相等匹配值加一
            if (dest.charAt(i) == dest.charAt(j)) {
                j++;
            }
            next[i]=j;
        }
        return next;
    }

除了s1[i]和s2[j]不相等时其余操作基本和暴力匹配相识

不相等时:
每次移动距离为失配字符前一个位置 - 失配字符前一个位置对应的next 值 j=next[j-1];

在这里插入图片描述

在这里插入图片描述

完整java代码实现:

package com.yg.algorithm;/*
@author  Mu_Mu
@date    2020/3/18  10:58
*/

public class KmpAlgorithm {
    public static void main(String[] args) {
        String str1="hahahahheheheha";
        String str2="heheheha";


        int []next=kmpNext(str2);
        System.out.println("index:"+kmpSearch(str1,str2,next));
    }

    //获取到一个字符串(子串)的部分匹配表
    public static int[] kmpNext(String dest) {
        //创建一个next数组保存部分匹配值
        int[] next = new int[dest.length()];
        //当只有一个字符时匹配值为0
        next[0]=0;
        for (int i = 1, j = 0; i < dest.length(); i++) {

            while (j>0&&dest.charAt(i) != dest.charAt(j)) {
            //相当于已遍历字符个数-对应部分匹配表的匹配值
                j=next[j-1];
            }
            //字符相等匹配值加一
            if (dest.charAt(i) == dest.charAt(j)) {
                j++;
            }
            next[i]=j;
        }
        return next;
    }

    public static int kmpSearch(String str1, String str2, int[] next) {
        for (int i = 0, j = 0; i < str1.length(); i++) {
            while (j > 0 && str1.charAt(i) != str2.charAt(j)) {
                j=next[j-1];
            }
            if (str1.charAt(i) == str2.charAt(j)) {
                j++;
            }
            if (j == str2.length()) {
                return i-j+1;
            }
        }
        return -1;
    }
}

图片以及部分文字参考:
https://www.cnblogs.com/zhangtianq/p/5839909.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法暴力匹配算法是两种字符串匹配算法,它们的主要区别在于匹配失败时的处理方式和求解next数组的方法。 1. 暴力匹配算法暴力匹配算法,也称为朴素匹配算法,是一种简单直接的字符串匹配方法。它的思想是从主串的第一个字符开始,逐个与模式串进行比较,如果匹配失败,则将主串的指针后移一位,再次与模式串进行比较,直到找到匹配或者主串遍历完毕。 2. KMP算法KMP算法是一种改进的字符串匹配算法,它通过预处理模式串,构建一个next数组,来实现在匹配失败时跳过一部分字符,从而提高匹配效率。KMP算法的核心思想是利用已经匹配过的信息,避免不必要的比较。 KMP算法的求解next数组的方法是通过模式串自身的特性来确定。具体步骤如下: - 首先,初始化next数组,next = -1,next = 0。 - 然后,从模式串的第二个字符开始,依次计算next[i]的值。 - 对于next[i]的计算,如果模式串的第i个字符与前面的字符匹配成功,next[i] = next[i-1] + 1;如果匹配失败,则需要根据已经匹配的信息来调整next[i]的值,具体调整方法是找到模式串的一个前缀子串,使得该前缀子串的后缀子串与模式串的前缀子串匹配,且长度最长。即next[i] = next[next[i-1]]。 在KMP算法中,当匹配失败时,根据next数组的值,可以直接将模式串的指针后移next[j]个位置,而不需要回溯到主串的前面重新开始匹配,从而提高了匹配效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值