kmp匹配算法
- 1.第一种方式是暴利匹配方式
- 2.第二种方式采用kmp 方式进行匹配
- 3. 相应的代码
1.第一种方式是暴利匹配方式
暴利匹配规则
模型: str1 位源字符串下标为i,str2位匹配字符串,下标为j 。 假设 str1 匹配到i , str2 匹配到j 则有
- (1)当 str1[i]==str2[j] 则 i++,j++ 继续匹配下一个字符串
- (2)当 str1[i]!=str2[j] 则 i=i-j+1(即 i向后移动一位),j则被置为0 即:j=0
- 暴利匹配存在的问题,是存在大量的回溯问题,若不匹配则,移动到下一位,接着匹配。
2.第二种方式采用kmp 方式进行匹配
实质是对算法的进一步优化。
- 主要是求出最长公共子序列的长度:规则是求前缀和后缀的共有元素
- 比较过程中相比 暴利匹配,不能直接回归到开始位置+1操作,而是找到公共位置字符串+1操作
- 找到公共部分,需要使用前缀,后缀的公共的部分,来计算出公共子序列。(计算出部分匹配表)
部分匹配表的产生
部分匹配值”就是前缀和后缀的最长的共有元素的长度
- 举例: 以“ABCDABD”为例
注意 !字符串为A 没有前缀和后缀,共有元素(匹配的值)为0;
思路分析:
1.先得到子串的部分匹配表
2.使用部分匹配表完成kmp匹配(kmp 思想 =已经匹配的值-部分匹配值)
3. 相应的代码
package acm;import java.util.Arrays;/*** @author qxl*/
public class KmpMatch {public static void main(String[] args) {String kmp ="abcdabcf";int[] ints = kmpMatch(kmp);System.out.println(Arrays.toString(ints));String str1="ababcddedfabc";String str2="abcda";kmpSearch(str1, str2);}private static int kmpSearch(String str1, String str2) {// 获取部分匹配表int[] next = kmpMatch(str2);for(int i = 0, j = 0; i< str1.length(); i++){while (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;}}public static int[] kmpMatch(String source){// 设置部分部分匹配标记 例如 0,0,0,1,2 表示 前缀后缀的公共部分为2int [] next=new int[source.length()];//字符串为1时 前缀和后缀为空集next[0]=0;// i=1 表示后缀,j=0 表示前缀for(int i=1,j=0;i<source.length();i++){// source.charAt(i) !=source.charAt(j) j需要已匹配的滑动窗口中获取新值next[j-1]while(j>0 && source.charAt(i)!=source.charAt(j)){j=next[j-1];}if(source.charAt(i)==source.charAt(j)){j++;}next[i]=j;}return next;}
}