浅谈字符串匹配KMP算法及代码实现

KMP算法是一种无回溯算法,由KnuthMorrisPratt等人发现,用以改进传统的字符串的模式匹配算法

思想:当在某个位置匹配不成功的时候可以根据之前的匹配结果从模式字符串的另一个位置开始,而不必从头开始匹配字符串

那么下次匹配的位置如何确定就成了问题关键

为了更好地阐述,我们引入几个概念

  • 前缀子串:模式串P开头的前k个字符, p0, p1 …,pk-1;
  • i位置的后缀子串:Pi位置的左边,取出k个字符,即pi-k+1,,pi;
  • i位的最长前缀串 :与i位置后缀子串相等的最长前缀子串。
  • 特征数n[i]:i位的最长前缀串的长度k就是模式串P在位置i上的特征数n[i];

  • 特征向量特征数组成的向量称为该模式串的特征向量

一旦匹配过程中pitj比较不等,可用p中以n [i-1]为下标的字符与tj进行比较

特征数定义:

举个例子,P=cococola

(如果浏览过万我就找可口可乐拉赞助去hhhhh)

特征数计算:

计算流程

匹配流程

还是以上文的字符串为例

算法复杂度

KMP匹配算法的时间复杂度O(m+n)

计算特征数的时间复杂度为O(m)

计算时间复杂度时采用了均摊分析的方法,在此很难展开说明,有兴趣可以自行了解

Java代码实现

    /**
     *
     * 在目标串中查找模式串首次出现的位置
     * @param haystack 目标串
     * @param needle 模式串
     * @return 0 模式串为空
     *          -1 无法匹配
     *          int 首次出现的第一个元素下标
     */
    public static int kmp(String haystack, String needle) {
        if (needle.equals("")) return 0;
        if (needle.length() > haystack.length()) return -1;
        int[] next = kmpnext(needle);
        for (int i = 0, j = 0; i < haystack.length(); i++) {
            while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
                j = next[j - 1];
            }
            if (haystack.charAt(i) == needle.charAt(j)) {
                j++;
            }
            if (j == needle.length()) {
                return i - j + 1;
            }
        }
        return -1;
    }

    /**
     * 得到模式串的特征向量
     * @param needle 模式串
     * @return int[] 特征向量
     */
    public static int[] kmpnext(String needle){
        int[] next = new int[needle.length()];
        next[0] = 0;
        for(int i = 1,j = 0; i < needle.length(); i++){
            while(j > 0 && needle.charAt(j) != needle.charAt(i)){
                j = next[j - 1];
            }
            if(needle.charAt(i) == needle.charAt(j)){
                j++;
            }
            next[i] = j;
        }
        return next;
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值