KMP算法与暴力匹配算法

应用场景 字符串匹配问题::
有一个字符串str1=“BBC ABCDAB ABCDABCDABDE”,和一个子串str2=“ABCDABD”
现在要判断str1 是否含有str2, 如果存在,就返回第一次出现的位置,如果没有,则返回-1

暴力匹配算法

如果用暴力匹配的思路,并假设现在str1匹配到i位置,子串str2匹配到 j 位置,则有
1)如果当前字符匹配成功( 即str1[i]==str2[j]),则i++, j++, 继续匹配下一个字符
2)如果失配(即str1[i]!=str2[j]) ,令i=i-(j-1), j=0。相当于每次匹配失败时,i
回溯,j被置为0.
3) 用暴力方法解决的话就会有大量的回溯,每次只移动一位,若是不匹配,移动到下一位接着判断,浪费了大量的时间。
4)暴力匹配算法实现.

public class ViolenceMatch {

	public static void main(String[] args) {
		String str1 = "32114 5456 89726541 32";
		String str2 = "1 32";
		int index = violenceMatch( str1, str2);
		System.out.println(index);
	}
	//暴力匹配算法
	public static int violenceMatch(String str1,String str2) {
		char[] s1 = str1.toCharArray();
		char[] s2 = str2.toCharArray();
		int s1len = s1.length;
		int s2len = s2.length;
		int i = 0;//指向s1
		int j = 0;//指向s2
		while(i<s1len && j<s2len) {
			//保证不越界
			
			if(s1[i] == s2[j]) {
				i++;
				j++;
			}else {
				//未匹配成功
				i = i - j + 1;
				j = 0;
			}
		}
		if(j == s2len) {
			//前面有++
			return i-j;
		}else {
			return -1;
		}
	}
}

KMP方法算法

利用之前判断过信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间

字符串匹配问题:
有一个字符串str1= “BBC ABCDABCDABDE”,和一个子串
str2="ABCDABD"现在要判断str1是否含有str2, 如果存在,就返回第一次出现的位置,如果没有,则返回-1
KMP主要作用 避免了子串内有重复字符的情况需要从头校验
如该字符串 结尾AB与头部AB相同 再校验到该最后的D不同的时候 可以直接比较子串头AB的后一位 (比较时原字符串指针不用动 需要移动的只是子串指针)


import java.util.Arrays;

public class KMPAlgorithm {
	//KMP主要作用 避免了子串内有重复字符的情况需要从头校验
	//如该字符串 结尾AB与头部AB相同 再校验到该最后的D不同的时候 可以直接比较子串头AB的后一位
	public static void main(String[] args) {
		String str1 = "BBC ABCDABCDABDE";
		String str2 = "ABCDABD";
		int[] next = kmpNext("ABCDABD");
		System.out.println(Arrays.toString(next));
		int index = kmpSearch(str1,str2,next);
		System.out.println(index);
	}
	//获取一个字符串子串的部分匹配值表
	public static int[] kmpNext(String dest) {
		//创建一个数组 保存部分匹配值
		int[] next = new int[dest.length()];
		next[0] = 0;//如果字符串长度为1 则部分匹配值为0
		for(int i = 1,j = 0;i<dest.length();i++) {
			while(j > 0 && dest.charAt(i) != dest.charAt(j) ) {
				
				j = next[j-1]; 
			}
			if(dest.charAt(i) == dest.charAt(j)) {
				//满足则匹配值加一
				j++;
			}
			next[i] = j;	
		}
		return next;
	}
	
	//kmp搜索算法
	public static int kmpSearch(String str1,String str2,int[] next) {
		//str1原字符串 str2子串  next子串部分匹配表
		for(int i = 0,j = 0;i<str1.length();i++) {
			while(j>0 && str1.charAt(i) != str2.charAt(j)) {
				//原字符串 指针不用动 需要移动的只是子串指针
				j = next[j-1]; 
			}
			
			if(str1.charAt(i) == str2.charAt(j)) {
				j++;
			}
			if(j == str2.length()) {
				return i - j +1; 
			}
		}
		return -1;
	}
}

你可能感兴趣的:(java,数据结构)