📅  最后修改于: 2023-12-03 15:10:44.794000             🧑  作者: Mango
在日常编程中,我们常常需要查找一个字符串中是否包含某个子字符串,或者需要统计某个子字符串在一个字符串中出现的次数。本文将介绍如何编写一个程序,实现查找指定子字符串中的字符串频率的查询。
我们可以使用两种算法来实现查找指定子字符串中的字符串频率的查询:暴力匹配算法和KMP算法。
暴力匹配算法,也称为朴素匹配算法,是最简单直观的字符串匹配算法。其思路是将模式串与主串的每个子串进行比较,如果匹配成功,则匹配成功。若匹配失败,则继续将模式串后移一个字符,从主串中的下一个字符开始继续匹配。
暴力匹配算法的时间复杂度为O(m*n),其中m为主串长度,n为子串长度。
下面是使用暴力匹配算法进行查找指定子字符串中的字符串频率的查询的代码片段:
public static int count(String str, String subStr) {
int count = 0; // 计数器
for (int i = 0; i <= str.length() - subStr.length(); i++) {
if (str.substring(i, i + subStr.length()).equals(subStr)) {
count++;
}
}
return count;
}
首先定义一个计数器count,然后对主串进行遍历,每次取主串的一个长度为子串长度的字符子串与子串进行比较,如果相等则计数器加一。最终返回计数器的值即为子串在主串中出现的次数。
KMP算法是一种改进的字符串匹配算法,其核心思想是利用模式串自身的特点,以达到快速匹配的目的。具体来说,KMP算法先预处理出模式串的“最大匹配值”数组next[],然后用该数组进行匹配。在进行匹配的过程中,当主串的某个字符与模式串匹配失败时,就可以利用next[]数组中的值来跳过一些不必要比较的字符,从而提高匹配的效率,降低算法的时间复杂度。
KMP算法的时间复杂度为O(m+n),其中m为主串长度,n为子串长度。
下面是使用KMP算法进行查找指定子字符串中的字符串频率的查询的代码片段:
public static int count(String str, String subStr) {
int count = 0; // 计数器
int[] next = getNext(subStr); // 获取next数组
int i = 0, j = 0;
while (i < str.length()) {
if (str.charAt(i) == subStr.charAt(j)) {
i++;
j++;
if (j == subStr.length()) {
count++;
j = next[j];
}
} else {
j = next[j];
if (j == -1) {
i++;
j = 0;
}
}
}
return count;
}
private static int[] getNext(String subStr) {
int[] next = new int[subStr.length() + 1];
next[0] = -1;
int i = 0, j = -1;
while (i < subStr.length()) {
if (j == -1 || subStr.charAt(i) == subStr.charAt(j)) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
return next;
}
首先同样定义一个计数器count,然后预处理出子串的“最大匹配值”数组next[]。接着用i和j分别表示主串和子串的匹配位置,初始化为0,然后在循环中进行匹配。当主串的某个字符与模式串匹配失败时,就可以利用next[]数组中的值来跳过一些不必要比较的字符,从而提高匹配的效率。匹配成功后,计数器加一,并将j赋值成next[j],继续进行匹配。最终返回计数器的值即为子串在主串中出现的次数。
本文介绍了如何编写一个程序,实现查找指定子字符串中的字符串频率的查询。我们可以选择暴力匹配算法或者KMP算法进行实现。其中,KMP算法具有更快的匹配效率和更低的时间复杂度,是一种更优秀的算法。