zoukankan      html  css  js  c++  java
  • 字符串——kmp


    一、前言

    kmp算法是用于从文本串text的字串中,寻找含有的模板串pattern的数量/位置的算法。
    例如,在文本串abcabcccabc中,模板串abc的数量有3个,其起始位置是0,3,8。

    二、思路

    暴力是两个for循环O(n*m)搞定,显然不够优雅,而kmp则是O(n+m)
    kmp说实话,有点绕,很多人不知道next数组的意义,但其实可以这样理解:
    寻找模板串中最长的相同后缀与前缀,并通过next数组存储
    如何理解?举个栗子
    对于模板串abcab而言,我们从头开始构造next数组。

    字串 前缀 后缀 最长公共前后缀 next数组
    "a" [] [] next[0] = 0
    "ab" [a] [b] next[1] = 0
    "abc" [a,ab] [c,bc] next[2] = 0
    "abca" [a,ab,abc] [a,ca,bca] a next[3] = 1
    "abcab" [a,ab,abc,abca] [b,ab,cab,bcab] ab next[4] = 2
    "abcabc" [a,ab,abc,abca,abcab] [c,bc,abc,cabc,bcabc] abc next[5] = 3

    对于文本串abcabb来说,当匹配到5,即abcabb时,模板串匹配到abcabc,此时该位置字符不同

    当使用暴力算法时,文本串必须跳回1位置,即b,而模板串必须跳回初始位置,重新匹配

    当使用kmp算法时,模板串next[当前位置-1 = 4] = 2,即跳到2位置,此时模板串为abc,而文本串为abcabb

    发现了吗?
    模板串前缀abc与文本串后缀abb拥有相同前缀ab,于是文本串就不需要回到原点了,可以继续对比,即此时文本串为abcab,而模板串为ab,然后对比接下来的字符。

    三、代码

    int nextt[maxn];
    void get_nextt(char pattern[]){//为pattern字符串创建nextt数组
        nextt[0] = 0;
        int max_length = 0;
        for(int i = 1;pattern[i];i++){
            // 这里是想要获取前缀的最长相同前后缀
            while(max_length > 0 && pattern[max_length] != pattern[i])
                max_length = nextt[max_length-1];
            if(pattern[i] == pattern[max_length])
                max_length++;
            nextt[i] = max_length;
        }
    }
    queue<int> search(char text[],char pattern[]){//从test字符串中,寻找含有多少个pattern字符串,并将其开头位置存入队列中
        queue<int> q;
        int pattern_length = strlen(pattern);
        get_nextt(pattern);
        int count = 0;
        for(int i = 0;text[i];i++){
            while(count > 0 && pattern[count] != text[i])
                count = nextt[count-1];
            if(pattern[count] == text[i])
                count++;
            if(count == pattern_length){
                q.push(i-pattern_length+1 );
                count = nextt[count-1];
            }
        }
        return q;
    }
    
  • 相关阅读:
    一个奇怪的网页bug 竟然是局域网DNS搞的鬼
    繁体系统下如何快速将简体安装文件乱码恢复正常?
    Ubuntu16.04LTS国内快速源
    bitnami redmine版本由2.3.1升级至3.2.2过程
    Ubuntu1404安装gogs过程
    AJAX
    jQuery 事件解释
    安装phpMyadmi报错
    总结二
    总结
  • 原文地址:https://www.cnblogs.com/MMMMMMMW/p/11607518.html
Copyright © 2011-2022 走看看