• KMP 大问题分割成小问题 分步理解


    KMP

    分解成小问题:

    1. 求出next数组
      • 求字符串前缀与后缀的公共子串长度
    2. 当pattern与text不匹配时,按照next数组的指示进行跳转

    求字符串前缀与后缀的公共子串长度

    字符串 absdc:

    前缀:a, ab, abs, absd, absdc

    真前缀:a, ab, abs, absd

    后缀:c, dc, sdc, bsdc, absdc

    真后缀:c, dc, sdc, bsdc

    用于next数组的应该是真前缀与真后缀的公共子串最大长度。

    int tmp = 0, res = 0;
    int len = s.length();
    int j = 0;
    for(int i = 1; i < len; i++){
        if(s[i] == s[j]){
            tmp ++;j++;
            res = tmp > res ? tmp : res;
        }
        else if(s[i] != s[j]){
            j = 0;
            tmp = 0;
            if(s[i] == s[j]){
                tmp ++;j++;
            	res = tmp > res ? tmp : res;
            }
        }
    }
    cout << res;
    

    这个是针对确定的一个字符串的比较暴力的算法,一旦不匹配就从头重新匹配。(因为针对确定的一个字符串,所以前缀都是从第一个开始的嘛,不匹配就从头再判断咯)

    求next数组

    其实构建next数组的本质就是求解pattern中的 前缀子串中的 最长公共前后缀。

    next[i] = k pattern[i]之前的子串中,存在最长长度为k的公共前后缀,因此可以把当前不匹配的text的位,与k+1位pattern再次进行比较。(但是因为数组是从0开始的,所以下标可以直接被赋值next数组中的值,而不用+1
    

    也就是它需要进行len-1次的上一节的行为。同时需要考虑尽可能重复利用结果(有点像KMP中patterntext不匹配时就使用next数组跳跃,这里也是利用next数组中已经产生的数据进行跳跃。

    想象两个指针,一个指向前缀的最后,一个指向后缀的最后,当它们的值不同时:

    i -> 前缀最后 j->从0到len-1循环的下标
    pattern[i] != pattern[j]时
    让i往回走,类似kmp
    i = next[i];//现在i是最长公共前后缀中前缀的后一位的下标
    

    当它们的值相同时,那公共前后缀的长度增加:

    next[++j] = ++i;注意next数组的下标对应的循环变量j
    使用next时,记住使用的下标的值是不匹配的当位。
    
    //字符串数组下标从0开始
    int next[pattern.length()+1];
    next[0] = -1;//用于pattern与text进行匹配且第一个数不匹配时
    int i = 0, j = -1;//i是循环变量,j是代表前缀最后比较的下标
    next[++i] = ++j;//初始化
    int len = pattern.length();
    while(i < len){//wihle循环变量用的是i
    if(pattern[i] == pattern[j])i
    	next[++i] = ++j;//next[i]作用是模式串在第i位不匹配了,就将下标i跳到next[i]处,所以next中应该使用循环变量i
    else
    	j = next[j];//不匹配时是j在回退
    }
    

    把pattern和text进行匹配,利用next数组加速

    j = 0; i = 0;//j是text的下标,i是pattern的下标
    while(j < text.length()){
    	while(i >= 0 && pattern[i] != text[j]){
        	i = next[i];
        }
        //循环退出,说明i<0或者当前位匹配
        i++; j++;//继续向后匹配
        //进行跳出判断
        if(i == len)
            return j-len
    }
    
  • 相关阅读:
    PowerDesigner中Table视图同时显示Code和Name
    sql语句 生成数据库表
    业务流程图
    物理模型图-数据库图
    观察者模式
    UML的九种图
    路由器工作原理
    web项目中处理捕获异常统一处理
    java中volatile、synchronized
    linux 安装软件的几种方法
  • 原文地址:https://www.cnblogs.com/peekapoooo/p/14159169.html
Copyright © 2020-2023  润新知