public class Main {
public static void main(String[] args) {
System.out.println(violentStringMatcher("abcabaabaabcacb", "abaabcac"));
System.out.println(kmpMatch("abcabaabaabcacb", "abaabcac"));
SundayMatch("abcabaabaabcacb", "abaabcac");
}
/**
* 暴力匹配,时间复杂度O(m*n)
* @param s 原字符串
* @param p 模式字符串
* @return
*/
public static int violentStringMatcher(String s, String p){
int i = 0, j = 0;
char[] s_arr = s.toCharArray();
char[] p_arr = p.toCharArray();
while (i < s.length() && j < p.length()){
if(s_arr[i] == p_arr[j]){
//当前字符串匹配成功,则继续比较后面的字符
i ++;
j ++;
}else{
//当前字符串匹配失败,则i回溯到原始位置+1处
i = i - j + 1;
j = 0;
}
}
if(j == p.length()){//匹配成功
return i - j;
}else {
return -1;
}
}
/**
* KMP算法
* @param s
* @param p
* @return
*/
public static int kmpMatch(String s, String p){
char[] s_arr = s.toCharArray();
char[] p_arr = p.toCharArray();
int i = 0, j = 0;
int[] next = getNextArray(p_arr);
while (i < s_arr.length && j < p_arr.length){
if(j == -1 || s_arr[i] == p_arr[j]){
//当前字符匹配成功,继续匹配下一字符
i ++;
j ++;
}else {
//当前字符匹配失败,i不变,j=next[j],即让p模式字符串右移j-next[j]个单位
j = next[j];
}
}
if (j == p_arr.length){
return i - j;
}else {
return -1;
}
}
/**
* 求模式字符串的next数组
* @param p_arr
* @return
*/
private static int[] getNextArray(char[] p_arr){
//已知next[k]的值,使用递归思想求出next[k+1]的值
//1、若k=-1或p[j]=p[k],则next[j+1]=next[k]+1;
//2、若p[j]!=p[k], 则令k=next[k],如果此时p[j]==p[k],则next[j+1]=k+1,
//如果不相等,则继续递归前缀索引,令k=next[k],继续判断,直至k=-1(即k=next[0])或者p[j]=p[k]为止
int[] next = new int[p_arr.length];
next[0] = -1;
int j = 0;
int k = -1;//k=next[j]=next[0]
while (j < p_arr.length - 1){
if(k == -1 || p_arr[j] == p_arr[k]){
k ++;
j ++;
next[j] = k;
}else {
k = next[k];
}
}
return next;
}
/**
* Sunday匹配
* @param s
* @param p
*/
public static void SundayMatch(String s, String p){
//Sunday算法是从前往后匹配,在匹配失败时关注的是文本串中参加匹配的最末位字符的下一位字符。
//如果该字符没有在模式串中出现则直接跳过,即移动位数 = 匹配串长度 + 1;
//否则,其移动位数 = 模式串中最右端的该字符到末尾的距离+1。
char[] s_arr = s.toCharArray();
char[] p_arr = p.toCharArray();
int s_length = s_arr.length;
int p_length = p_arr.length;
int i = 0, j = 0;
while (i <= s_length - p_length + j){
if (s_arr[i] == p_arr[j]){
if (j == p_length - 1){
System.out.println(i - j);
i = i - j + 1;
j = 0;
}else {
i ++;
j ++;
}
}else{
if (i == s_length - p_length + j){
break;
}
int pos = contains(p_arr, s_arr[i + p_length - j]);
if (pos == -1){
//不匹配时关注文本串中参加匹配的最末位字符的下一位字符
i = i + p_length - j + 1;
j = 0;
}else {
//匹配时移动位数 = 模式串中最右端的该字符到末尾的距离+1
i = i + p_length - j - pos;
j = 0;
}
}
}
}
/**
* 从后往前判断
* @param chArray
* @param ch
* @return
*/
private static int contains(char[] chArray, char ch){
for (int i = chArray.length - 1; i >= 0; i --){
if (chArray[i] == ch){
return i;
}
}
return -1;
}
}
字符串匹配KMP算法、Sunday算法
最新推荐文章于 2025-04-13 17:39:05 发布