如何用Java实现KMP字符串匹配算法?

KMP算法是一种高效的字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。它通过利用已经匹配过的字符信息,避免不必要的回溯操作,提高了匹配的效率。

KMP算法的核心思想是构建一个最大公共前后缀表(也称为部分匹配表),根据该表在匹配过程中确定模式串向后移动的位置。下面将详细介绍KMP算法的实现步骤和Java代码。

一、构建最大公共前后缀表

最大公共前后缀表是一个长度与模式串相等的数组,用于存储每个位置对应的最大公共前后缀长度。具体的构建方法如下:

1、初始化最大公共前后缀表为一个与模式串长度相同的数组,默认值都为0。

2、从第二个位置开始遍历模式串,依次计算每个位置对应的最大公共前后缀长度。

1)、假设当前位置为i,已知前i-1个位置的最大公共前后缀长度为prefixLen[i-1]。

2)、如果模式串的第prefixLen[i-1]个字符与模式串的第i个字符相等,则最大公共前后缀长度为prefixLen[i-1]+1。

3)、否则,继续往前查找长度为prefixLen[i-1]的最大公共前后缀,直到找到相等的字符或长度为0。

4)、更新prefixLen[i]为找到的最大公共前后缀的长度。

以下是使用Java代码实现构建最大公共前后缀表的函数:

private int[] buildPrefixTable(String pattern) {
    int[] prefixLen = new int[pattern.length()];
    prefixLen[0] = 0;

    int len = 0;
    int i = 1;

    while (i < pattern.length()) {
        if (pattern.charAt(i) == pattern.charAt(len)) {
            len++;
            prefixLen[i] = len;
            i++;
        } else {
            if (len != 0) {
                len = prefixLen[len - 1];
            } else {
                prefixLen[i] = 0;
                i++;
            }
        }
    }

    return prefixLen;
}

二、KMP算法的匹配过程

KMP算法的匹配过程分为主串与模式串的对比和模式串的后移两个步骤。具体的实现如下:

1、初始化一个指针i指向主串的第一个位置,一个指针j指向模式串的第一个位置。

2、在匹配过程中,一直循环直到到达主串的末尾或找到了一个匹配的位置。

1)、如果主串的第i个字符与模式串的第j个字符相等,则同时将i和j都向后移动一位。

2)、如果j已经到达模式串的末尾,说明找到了一个匹配的位置,将该位置记录下来(可以是存储到一个List中或直接打印)。

3)、如果主串的第i个字符与模式串的第j个字符不相等:根据最大公共前后缀表,将模式串向右移动j - prefixLen[j-1]位。如果prefixLen[j-1]为0,则将模式串向右移动一位。注意:主串的指针i不需要回溯,继续与新的j进行对比。

以下是使用Java代码实现KMP算法的匹配过程:

public List kmpMatch(String text, String pattern) {
    List positions = new ArrayList<>();
    int n = text.length();
    int m = pattern.length();
    int[] prefixLen = buildPrefixTable(pattern);

    int i = 0; // 主串指针
    int j = 0; // 模式串指针

    while (i < n) {
        if (text.charAt(i) == pattern.charAt(j)) {
            i++;
            j++;
        }

        if (j == m) { // 找到一个匹配位置
            positions.add(i - j);
            j = prefixLen[j - 1];
        } else if (i < n && text.charAt(i) != pattern.charAt(j)) {
            if (j != 0) {
                j = prefixLen[j - 1];
            } else {
                i++;
            }
        }
    }

    return positions;
}

三、KMP算法的应用举例

使用KMP算法,我们可以在一个主串中高效地查找一个模式串的出现位置。以下是一个简单的示例代码:

public static void main(String[] args) {
    String text = "ABABDABACDABABCABAB";
    String pattern = "ABABCABAB";
    List positions = kmpMatch(text, pattern);
    System.out.println("Pattern found at positions: " + positions);
}

输出结果为:Pattern found at positions: [10]

表示在主串text的位置10处找到了与模式串pattern相匹配的子串。

KMP算法的时间复杂度为O(n+m),其中n为主串的长度,m为模式串的长度。相对于简单的暴力匹配算法,KMP算法具有更高的效率和优化性能。

你可能感兴趣的:(java,算法,字符串匹配,KMP)