KMP模式匹配算法

求一个字符串(模式串)在另一个字符串(主串)中的位置,称为字符串模式匹配

朴素字符串模式匹配
  • 在朴素的字符串模式匹配算法中,对主串S和模式串T分别设置指针i和j,假设字符串下标从0开始,初始时i和j分别指向每个串的第0个位置。在第n趟匹配开始时,i指向主串S中的第n-1个位置,j指向模式串T的第0个位置,然后逐个向后比较。若T中的每一个字符都与S中的字符相等,则称匹配成功;否则,当遇到某个字符不相等时,i重新指向S的第n个位置,j重新指向T的第0个位置,继续进行第n+1趟匹配。
KMP
  • 利用已经得到的部分匹配,使模式串尽可能多的向右滑动一段距离。

  • 利用next数组,存部分匹配值( 模式串前后缀的最长共有元素长度

    例如:ABCDABD的next数组为: 以当前位置为结尾的模式串的前后缀的公共部分 在这里插入图片描述
    ”A”的前缀和后缀都为空集,共有元素的长度为0;
    ”AB”的前缀为[A],后缀为[B],共有元素的长度为0;
    ”ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
    ”ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
    ”ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1;
    ”ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;
    ”ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

  • 那么在不匹配的位置时,查找匹配失败的位置的前一个位置的next值,然后已经匹配成功的位数-next值,得到向右移动的位数。

  • 例如:Str1 = “BBC ABCDAB ABCDABCDABDE”,Str2 = “ABCDABD”
    在这里插入图片描述
    在D匹配失败,则查找B的next=2。已经匹配成功的ABCDAB=6,则向右移动6-2=4位:在这里插入图片描述

  • Java实现:

	public class KMP {

        public static void main(String[] args) {
        System.out.println(kmp("abcabaabaabcacb", "abaabcac"));
    }
	
	//next数组
    public static int[] getNext(char[] t) {
        int[] next = new int[t.length];
        next[0] = -1;
        next[1] = 0;
        int k;
        
        for (int j = 2; j < t.length; j++) {
            k=next[j-1];
            while (k!=-1) {
                if (t[j-1] == t[k]) {
                    next[j] = k + 1;
                    break;
                }
                else {
                    k = next[k];
                    next[j] = 0;  
                }
            }
        }
        return next;
    }

    //若匹配成功,返回t在s中的位置(第一个相同字符对应的位置),否则返回-1
    public static int kmp(String s, String t){
        char[] sarr = s.toCharArray();
        char[] tarr = t.toCharArray();
        int[] next = getNext(tarr);
        
        int i = 0, j = 0;
        while (i<sarr.length && j<tarr.length){
            if(j == -1 || s_arr[i]==tarr[j]){
                i++;
                j++;
            }
            else
                j = next[j];
        }
        if(j == tarr.length)
            return i-j;
        else
            return -1;
    }
}

【参考文档】
KMP算法详解及其Java实现
KMP算法详解与Java实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值