zoukankan      html  css  js  c++  java
  • KMP

    具体学习:

    请参照,讲解的非常详细:https://blog.csdn.net/v_july_v/article/details/7041827

    KMP解决的问题:字符串中查找。如:S(文本串)=‘aaab’,P(模式串)=‘aab’,在S中查找是否包含P

    暴力的解法:遍历S的时候,匹配P,时间复杂度O(n*m),S 长度n,P 长度m。

    而KMP方法时间复杂度,O(n+m),与暴力解是质的变化。

    首先了解这个概念: 

    字符前面的前缀与后缀的最长匹配长度(记为MML:max match length):(1)前缀和后缀的长度要相等。(2)前缀和后缀的字符串要相等。(3)前缀和后缀的长度要最长。(4)前缀不能包含最后一个字符,后缀不能包含第一个字符。(5)不包含这个字符本身,是在当前字符的前面字符串中找。

    举例:abcabcd。例如dMML是3。因为‘abc’== ‘abc’。

    next[]数组:即,P中每个字符的MML,人为规定next[0] = -1,next[1] = 0。

    KMP算法的流程,因为有了next数组。举例如下:

    S = aabcdeaaf

    P = aabcdeaak, next [] = {-1, 0, 1, 0, 0 ,0 ,0, 1,  2};

    KMP的算法流程(引用了大佬的,自己写的讲不清楚):假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置
        如果当前字符匹配成功(即[S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
        如果当前字符匹配失败(即S[i] != P[j]),再如果 next[j] == -1,则 i++,j不变。否则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了 j - next [j] 位。
        我们发现如果某个字符匹配成功,模式串首字符的位置保持不动,仅仅是i++、j++;如果匹配失配,i 不变(即 i 不回溯),模式串会跳过匹配过的next [j]个字符。整个算法最坏的情况是,当模式串首字符位于i - j的位置时才匹配成功,算法结束。
        所以,如果文本串的长度为n,模式串的长度为m,那么匹配过程的时间复杂度为O(n),算上计算next的O(m)时间,KMP的整体时间复杂度为O(m + n)。

    代码

    package basic_class_02;
    
    public class Code_01_KMP {
    
    	public static int getIndexOf(String s, String m) {
    		if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
    			return -1;
    		}
    		char[] ss = s.toCharArray();
    		char[] ms = m.toCharArray();
    		int si = 0;
    		int mj = 0;
    		int[] next = getNextArray(ms);
    		while (si < ss.length && mj < ms.length) {
    			if (ss[si] == ms[mj] ) { 
    				si++;
    				mj++;
    			} else if(next[mj] == -1){ 
    				si++;
    			} else{
    				mj = next[mj];
    			}
    		}
    		return mj == ms.length ? si - mj : -1;  // ms 匹配到结尾了,说明已经匹配成功过
    	}
    
    	public static int[] getNextArray(char[] ms) {  // next数组获取
    		if (ms.length == 1) {
    			return new int[] { -1 };
    		}
    		int[] next = new int[ms.length];
    		next[0] = -1;
    		next[1] = 0;
    		int pos = 2;
    		int cn = 0;
    		while (pos < next.length) {
    			if (ms[pos - 1] == ms[cn]) {
    				next[pos++] = ++cn;
    			} else if (cn > 0) {
    				cn = next[cn];
    			} else {
    				next[pos++] = 0;
    			}
    		}
    		return next;
    	}
    
    	public static void main(String[] args) {
    		String str = "abcabcababaccc";
    		String match = "ababa";
    		System.out.println(getIndexOf(str, match));
    
    	}
    
    }
    

    当然肯定有比KMP更加优秀的算法,如BMSunday算法。上文链接中,讲解到了,推荐一看,流程比KMP还要简单。

  • 相关阅读:
    ubuntu studio
    BeanUtils包的学习
    java的GUI编程
    Mybatis之旅第三篇-SqlMapConfig.xml全局配置文件解析
    Mybatis之旅第二篇-Mapper动态代理方式
    Mybatis之旅第一篇-初识Mybatis
    Spring之旅第六篇-事务管理
    Spring之旅第五篇-AOP详解
    Spring之旅第三篇-Spring配置详解
    Spring之旅第二篇-Spring IOC概念及原理分析
  • 原文地址:https://www.cnblogs.com/horken/p/10706119.html
Copyright © 2011-2022 走看看