KMP算法的理解

KMP算法的理解


串的模式匹配,BF算法,采用了穷举法进行匹配。每次匹配不成功都需要回溯,模式串与目标串均需要回溯。
例:
模式串:12112
目标串:12121211121121
模式串相对目标串进行匹配!

一、KMP算法

进行串的模式匹配,KMP算法相对采用穷举法进行模式匹配,消除了主串指针的回溯,提高了算法效率。

二、KMP算法匹配例图


KMP算法:消除主串的回溯,利用模式串的前缀表进行移动,根据模式串的前缀后缀相同,模式串的前缀和对应主串匹配的子串后缀对应,减少匹配次数。

三、实现代码

//获取初始前缀表:
 private static int[] getPrefixTable(int[] prefixTable, char[] charArray) {

        int length = 0;//最大公共前后缀长度
        prefixTable[0] = 0;//前后缀数组第一个默认为0,首元素自身不算前后缀相同
        int index = 1;//数组下标

        /*
        * 前后缀数组的首元素的下标默认为0,即初始从第二个与第一个比较
        * 例:12112  
        * 		1、  1 2
        * 		2、  1   1
        * 		3、    2   1
        * 		4、  1     1
        * 		5、    2     2
        * */
        while(index<charArray.length){
            if(charArray[index]==charArray[length]){
                length++;
                prefixTable[index] = length;
                index++;
            }else{
                if(length>0){
                    length--;//回到上一位
                }
                prefixTable[index] =length;
                index++;
            }
        }
    return prefixTable;
    }
// 2.重置前缀表:

//所有元素后移一位,首元素置为零。
//应注意,数组长度与下标的关系,相差1。
private static void moveEletment(int[] prefixTable) {
        int length = prefixTable.length;
        for(int i = 1; i<prefixTable.length;i++){
            prefixTable[length-i] = prefixTable[length-i-1];
        }
        prefixTable[0] = -1;
    }
// 3.串匹配
/**
     *
     * @param charArray  模式串
     * @param charArray1   目标串
     * @param prefixTable   前缀数组
     */
    public static void patternMatch(char[] charArray, char[] charArray1, int[] prefixTable) {

        int i = 0;//做模式串的移动下标
        int j = 0;//做目标串的移动下标

        while(j<charArray1.length){
            if(i == charArray.length-1 && charArray[i]==charArray1[j]){
                System.out.println("匹配成功开始下标:"+(j-i));//j-i,表示匹配成功后的起始下标
                i = prefixTable[i];//匹配成功后,继续往后匹配
            }
            if(charArray[i]==charArray1[j]){
                i++;
                j++;
            }else{
                //不相等,移动子串(根据前后缀表对应的值进行移动对齐)
                i = prefixTable[i];
                if(i ==-1){
                    i++;
                    j++;
                }
            }
        }
    }
   public static void main(String[] args) {

        String str = "12121";
        char[] charArray = str.toCharArray();

        String str1 = "121211212121";
        char[] charArray1 = str1.toCharArray();

        int[] prefixTable = new int[charArray.length];

        prefixTable = getPrefixTable(prefixTable,charArray);
        moveEletment(prefixTable);
        patternMatch(charArray,charArray1,prefixTable);
        
    }

在这里插入图片描述

总结

模式串与目标串匹配,匹配不成功时,查看匹配成功目标串的子串对应的模式串的前缀表值。进行模式串的前缀与子串的后缀对应,减少匹配的次数。在匹配的过程中,目标串消除了回溯,提高了算法效率。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值