KMP算法-Next数组递归求法

题目:

在一个字符串s中,找到第一个与给定的字符串t想匹配的位置

递归求next数组

    /**
     * 递归求next数组
     * <p>
     * 原理:若求next[k+1],其实分两种情况:
     * <p>
     * 目前已知 next[k],假设 next[k] = m ;
     * <p>
     * 1. 若t[m] == t[k], 则 next[k] = m+1;
     * <p>
     * 2. 若t[m] != t[k],则 已知 next[m] 的值,假设为 next[m]=d;
     * <p>
     * 则说明:在数组下标从0m的子数组前后最长子串的长度为d
     * <p>
     * 因此,又分为两种情况:
     * <p>
     * a. 若 t[d] == t[k], 则 next[k] = d+1 ;
     * <p>
     * b. 若 t[d] != t[k], 则 m = d,回到 2
     * <p>
     * 事实上,上述步骤 a 和 b 只不过是将步骤 12 中的 m 换成 d 的重复
     */
    private static int[] getNext1(String[] t) {
        int[] next = new int[t.length];
        next[0] = -1;
        int m = -1;
        // 当前计算的是next[i+1]的值,故i从0到t.length-1
        int i = 0;
        while (i < t.length - 1) {
            if (m == -1 || t[m] == t[i]) {
                //next[i]到next[i+1]实际步长只能是01两个中的一个,故最多+1
                m++;
                i++;
                next[i] = m;
            } else {
                m = next[m];
            }
        }
        return next;
    }

m = next[m]的由来

由上述代码分析可知:

若求next[k+1],其实分两种情况:
目前已知 next[k],假设 next[k] = m 。
1. 若t[m] == t[k], 则 next[k] = m+1;
2. 若t[m] != t[k],则 已知 next[m] 的值,假设为 next[m]=d;
则现在所求的最长前后缀串 出现在 数组下标从 0 到 d 和 k-d+1到 k-d 中,循环 步骤 1;

分析:每次求的d = next[ next[k] ], 然后将 d 的值赋给 m 重复 1,即此时的 m= next[next[k]],而由 步骤1 可知 m = next[k],故 m 的值没此都是 对next[k] 求next[]的值,因此在递归过程中只需让:m = next[m]循环即可

测试代码:

```
public class KMP {

    public static void main(String[] args) {

        String[] s = new String[] { "a", "b", "c", "a", "b", "a", "b", "c", "a" };// 主串
        String[] t = { "a", "b", "a", "b" };// 待匹配的串
        // 非递归求next数组:
        // int[] next = getNext(t);
        // 递归求next数组:
        int[] next = getNext1(t);

        System.out.print("next数组为:");
        for (int i : next) {
            System.out.print(i + " ");
        }

         getResult(s, t, next);
    }

    private static void getResult(String[] s, String[] t, int[] next) {
        int i = 0;
        int j = 0;

        while (i < s.length && j < t.length) {
            if (next[j] == -1 || s[i] == t[j]) {
                i++;
                j++;
            } else {
                j = next[j];
            }

            if (j == t.length - 1) {
                if (s[i] == t[j]) {
                    System.out.println("\n匹配串在主串中首次出现的位置为:" + (i - j));
                } else {
                    System.out.println("\n匹配失败");
                }
                break;
            }
        }
    }

运行结果:

next数组为:-1 0 0 1
匹配串在主串中首次出现的位置为:3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值