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

Java函数实现字符串匹配算法的例子

发布时间:2023-06-26 09:37:19

字符串匹配是计算机中比较基础的算法之一,主要是用来判断一个字符串中是否包含和另一个字符串相同的子串。在工程实践中,字符串匹配算法具有广泛的应用,比如文本编辑器中的搜索和替换、数据库中的查询操作等等。本篇文章将通过Java语言详细探讨几种字符串匹配算法及其实现。

一、朴素字符串匹配算法

朴素字符串匹配算法是最简单和常见的字符串匹配算法,其实现思路是通过两个嵌套的循环遍历主串和模式串,将主串中所有可能的子串与模式串进行一一比较,找到第一个相同的子串则匹配成功。但这种算法的时间复杂度高达O(mn),其中m和n分别为主串和模式串的长度,因此其适用范围比较有限。

下面是Java实现朴素字符串匹配算法的示范代码:

public static int naiveStringMatch(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;                              // 匹配失败
}

二、KMP字符串匹配算法

KMP字符串匹配算法(Knuuth-Morris-Pratt)是一种比朴素算法更优的字符串匹配算法,其核心思想是通过预处理模式串,使得在匹配过程中每次失配时可以尽可能地避免已经匹配过的字符。这种算法的时间复杂度为O(m+n),其中m和n分别为主串和模式串的长度,因此具有很高的效率。

下面是Java实现KMP字符串匹配算法的示范代码:

public static int KMPStringMatch(String text, String pattern) {
    int n = text.length();
    int m = pattern.length();
    int[] next = getNext(pattern);          // 模式串的next数组
    int i = 0, j = 0;
    while (i < n && j < m) {
        if (j == -1 || text.charAt(i) == pattern.charAt(j)) {
            i++;
            j++;
        } else {
            j = next[j];                    // 失配时跳转到模式串的next位置
        }
    }
    if (j == m)
        return i - j;                       // 返回匹配位置下标
    else
        return -1;                          // 匹配失败
}

// 计算模式串的next数组
public static 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;
}

三、Boyer-Moore字符串匹配算法

Boyer-Moore字符串匹配算法是一种基于字符比较位置的字符串匹配算法,其核心思想是从模式串最后一个字符开始匹配,不匹配时通过预处理得到的坏字符表(bad character table)和好后缀表(good suffix table)来决定移动模式串的位置,尽可能地跳过已经匹配过的字符。这种算法的时间复杂度为O(mn),但其在实际应用中常常比KMP算法更快,因为它可以跳过更多的无效匹配。

下面是Java实现Boyer-Moore字符串匹配算法的示范代码:

public static int BMStringMatch(String text, String pattern) {
    int n = text.length();
    int m = pattern.length();
    int[] bc = buildBC(pattern);            // 模式串的坏字符表
    int[] suffix = new int[m];              // 模式串的好后缀表
    boolean[] prefix = new boolean[m];      // 模式串的好后缀前缀表
    preprocess(pattern, suffix, prefix);    // 预处理模式串
    int i = 0;
    while (i <= n - m) {
        int j = m - 1;
        while (j >= 0 && text.charAt(i + j) == pattern.charAt(j)) {
            j--;
        }
        if (j < 0)                          // 匹配成功
            return i;
        else {
            int x = j - bc[text.charAt(i + j)];
            int y;
            if (j < m - 1) {
                y = moveBySuffix(j, suffix, prefix);
            } else {
                y = 1;
            }
            i += Math.max(x, y);
        }
    }
    return -1;                              // 匹配失败
}

// 计算模式串的坏字符表
public static int[] buildBC(String pattern) {
    int m = pattern.length();
    int[] bc = new int[256];
    Arrays.fill(bc, -1);
    for (int i = 0; i < m; i++) {
        bc[pattern.charAt(i)] = i;
    }
    return bc;
}

// 预处理模式串
public static void preprocess(String pattern, int[] suffix, boolean[] prefix) {
    int m = pattern.length();
    for (int i = 0; i < m; i++) {
        suffix[i] = -1;
        prefix[i] = false;
    }
    for (int i = 0; i < m - 1; i++) {
        int j = i;
        int k = 0;
        while (j >= 0 && pattern.charAt(j) == pattern.charAt(m - 1 - k)) {
            j--;
            k++;
            suffix[k] = j + 1;
        }
        if (j == -1)
            prefix[k] = true;
    }
}

// 根据好后缀表和好后缀前缀表计算移动距离
public static int moveBySuffix(int j, int[] suffix, boolean[] prefix) {
    int k = suffix[j + 1];
    if (k > -1)
        return j - k + 1;
    for (k = j + 2; k < suffix.length; k++) {
        if (prefix[suffix.length - k])
            return k;
    }
    return suffix.length;
}

综上所述,字符串匹配算法在实际应用中具有广泛的应用,Java作为一门广泛使用的编程语言,提供了丰富的字符串处理函数和类,方便开发者实现各种复杂的字符串匹配和操作功能,同时也为算法实现提供了良好的基础支持。在算法的选择和实现中,我们需要根据实际应用场景进行综合评估,选择最佳算法和优化手段来提高系统性能和用户体验。