数据结构-暴力匹配和KMP算法(Java实现)

暴力匹配

大量的回溯极其影响效率

package datastructure.kmp;

/*
    @CreateTime 2021/9/23 17:17
    @CreateBy cfk
    字符串暴力匹配法
*/

public class ViolenceMatch {

    public static void main(String[] args) {

        int i = violenceMatch("nhadsf sladfjcfk a", "cfk");
        System.out.println(i);


    }

    public static int violenceMatch(String s1, String s2) {
        //分别把两个字符串都转为字符数组方便后面匹配字符
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();

        //定义两个变量作为数组的指针记录
        int i = 0;
        int j = 0;

        //当两个数组没有遍历完时,一直遍历
        while (i < str1.length && j < str2.length) {
            if (str1[i] == str2[j]) {
                i++;
                j++;
            }else {
                i = i - (j - 1);
                j = 0;
            }
        }

        //判断是否有找到对应字符串
        if (j == str2.length) {
            return i-j;
        }else {
            return -1;
        }

    }
}

kmp算法

核心是计算出字串的匹配表

package datastructure.kmp;

/*
    @CreateTime 2021/9/23 21:36
    @CreateBy cfk
    KMP算法
*/

import java.util.Arrays;

public class KMPMatch {
    public static void main(String[] args) {
        String s1 = "BBC ABCDAB ABCDABCDABDE";
        String s2 = "ABCDABD";

        int[] next = kmpNext(s2);
        System.out.println(Arrays.toString(next));
        System.out.println(kmpMatch(s1, s2, next));


    }

    //kmp算法实现
    public static int kmpMatch(String s1, String s2, int[] next) {
        for (int i = 0,j = 0; i < s1.length(); i++) {
            //不相等时,i不动,j继续往前 在比较 找到最大长度的匹配值
            //移动的长度和匹配表有关
            while (j > 0 && s1.charAt(i) != s2.charAt(j)) {
                j = next[j-1]; //比较难理解 算法的核心
            }
            

            //如果相等
            if (s1.charAt(i) == s2.charAt(j)) {
                j++;
            }

            //当j的长度与字符串2的长度相等时,说明已经找到了
            if (j == s2.length()) {
                return i-j+1;
            }
        }
        return -1;
    }

    //获取子串的匹配值表
    public static int[] kmpNext(String str){

        //创建一个和字串等长的数组
        int[] next = new int[str.length()];

        //把数组的第一位置为0,因为当数组只有一个数时匹配的为0
        next[0] = 0;

        for (int i = 1, j = 0; i < str.length(); i++) {
            //当遇到不相等的元素 并且前面有相等的元素(因为此时j的值不为0)
            //让指针回到前面遇到的第一个不相同的元素 比如 ABCDABD  在判断最后一位时直接应该把指针放在B上面
            //                                   0000120  即next[j-1]对应1
            while (j > 0 && str.charAt(i) != str.charAt(j)) {
                j = next[j-1]; //比较难理解 算法的核心
            }


            //当遇到两个元素相等的时候 让记录匹配值加一,如果第二位也相等则再加一 以此类推 最后把值赋给当前位置字符
            if (str.charAt(i) == str.charAt(j)){
                j++;
            }
            next[i] = j;

        }

        return next;

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值