欢迎访问宙启技术站
智能推送

Java函数实现字符串匹配的基本算法

发布时间:2023-09-23 17:43:58

字符串匹配是计算机科学中一个重要的问题,指的是在一个主字符串中寻找一个模式字符串的出现位置。实现字符串匹配的基本算法有多种方法,下面将介绍三种常用的算法:暴力匹配、KMP算法和Boyer-Moore算法。

1. 暴力匹配算法(Brute-Force)

暴力匹配算法是最简单直观的方法,它的思路是从主字符串的每个位置开始,逐个比较模式字符串的字符是否匹配。如果匹配成功,继续比较下一个字符,如果不匹配,则将主字符串的指针向后移动一位。

public int indexOf(String text, String pattern) {
    int n = text.length();
    int m = pattern.length();
    for (int i = 0; i <= n - m; i++) {
        int j;
        for (j = 0; j < m; j++) {
            if (text.charAt(i + j) != pattern.charAt(j)) {
                break;
            }
        }
        if (j == m) {
            return i;
        }
    }
    return -1;
}

该算法的时间复杂度是O(n * m),其中n是主字符串的长度,m是模式字符串的长度。

2. KMP算法(Knuth-Morris-Pratt)

KMP算法是一种优化暴力匹配算法的字符串匹配算法。它利用模式字符串的部分匹配表来避免不必要的比较操作。首先,通过对模式字符串构建部分匹配表,计算出每个位置的最长相同前缀后缀的长度;然后,在匹配过程中,当出现不匹配时,根据部分匹配表可以直接跳过多个字符,将模式字符串向右移动。

public int indexOf(String text, String pattern) {
    int n = text.length();
    int m = pattern.length();
    int i = 0, j = 0;
    int[] next = getNext(pattern);
    while (i < n && j < m) {
        if (j == -1 || text.charAt(i) == pattern.charAt(j)) {
            i++;
            j++;
        } else {
            j = next[j];
        }
    }
    if (j == m) {
        return i - j;
    } else {
        return -1;
    }
}

private int[] getNext(String pattern) {
    int m = pattern.length();
    int[] next = new int[m];
    next[0] = -1;
    int i = 0, j = -1;
    while (i < m - 1) {
        if (j == -1 || pattern.charAt(i) == pattern.charAt(j)) {
            i++;
            j++;
            next[i] = j;
        } else {
            j = next[j];
        }
    }
    return next;
}

KMP算法的时间复杂度是O(n + m),其中n是主字符串的长度,m是模式字符串的长度。

3. Boyer-Moore算法

Boyer-Moore算法是一种更高效的字符串匹配算法,它利用模式字符串中的字符分布规律来进行匹配。它的核心思想是从主字符串的末尾开始,逐个将模式字符串与主字符串从后往前进行比较。当出现不匹配时,根据字符在模式字符串中的位置和Bad Character规则或Good Suffix规则,选择合适的移动方式,将模式字符串向右移动。

public int indexOf(String text, String pattern) {
    int n = text.length();
    int m = pattern.length();
    int[] badChar = buildBadChar(pattern);
    int[] suffix = buildSuffix(pattern);
    int i = m - 1, j = m - 1;
    while (i < n) {
        if (text.charAt(i) == pattern.charAt(j)) {
            if (j == 0) {
                return i;
            }
            i--;
            j--;
        } else {
            int x = badChar[text.charAt(i)];
            int y = suffix[j];
            i += Math.max(x, y);
            j = m - 1;
        }
    }
    return -1;
}

private int[] buildBadChar(String pattern) {
    int m = pattern.length();
    int[] badChar = new int[256];
    for (int i = 0; i < 256; i++) {
        badChar[i] = m;
    }
    for (int i = 0; i < m - 1; i++) {
        badChar[pattern.charAt(i)] = m - i - 1;
    }
    return badChar;
}

private int[] buildSuffix(String pattern) {
    int m = pattern.length();
    int[] suffix = new int[m];
    suffix[m - 1] = m;
    int f = 0, g = m - 1;
    for (int i = m - 2; i >= 0; i--) {
        if (i > g && suffix[i + m - 1 - f] < i - g) {
            suffix[i] = suffix[i + m - 1 - f];
        } else {
            if (i < g) {
                g = i;
            }
            f = i;
            while (g >= 0 && pattern.charAt(g) == pattern.charAt(g + m - 1 - f)) {
                g--;
            }
            suffix[i] = f - g;
        }
    }
    return suffix;
}

Boyer-Moore算法的时间复杂度是O(n + m),其中n是主字符串的长度,m是模式字符串的长度。

这三种算法都是经典的字符串匹配算法,它们在实际应用中有不同的优劣势和适用范围。我们可以根据具体的应用场景选择适合的算法来实现字符串匹配。