zoukankan      html  css  js  c++  java
  • 数据结构--KMP算法(字符串匹配算法)

    两个字符串str1, str2,str2是否是str1的子串,若是,返回子串开始的位置。

    利用前面匹配过的信息指导后面的匹配,可以起到加速的作用

    某一个字符的最长前缀(不能包含最后一个元素)和最长后缀(不能包含第一个元素)的匹配长度组成一个数组next()数组

    1.求str2的next()数组

      0位置的默认-1

      1位置的默认0

      后面的都要求出其最长前缀和最长后缀的匹配长度  组成next数组

    2.str1与str2进行匹配时,若在x,y位置不匹配,则查str2的next数组,找到y位置的最长前缀和最长后缀的匹配长度,然后将匹配长度对应到str1中的 j 位置

    将str2的0位置对应到 j 位置,然后匹配x位置和最长前缀和最长后缀的匹配长度的下一个位置

    再开始匹配,匹配的位置是x位置和str2中最长前缀和最长后缀匹配长度的下一个位置

    开始匹配时:当x 位置与y位置不匹配时,则查str2的next数组,找到y位置的最长前缀和最长后缀的匹配长度

    然后将匹配长度对应到str1中的 j 位置

    将str2的0位置对应到 j 位置,

    然后匹配x位置和最长前缀和最长后缀的匹配长度的下一个位置 : x位置与z位置

     

    求next数组的方法:

    0位置  -1

    1位置  0

    2位置  0 和1 位置相同为1,不同为0

    其他位置:在求 i 位置的next数组时,找 i - 1位置的next数组指向的位置的下一个元素与 i - 1比较,、

    如果相等,则 i 位置的next数组的值为 i - 1位置的next数组的值 + 1

    如果不想等,则向上找到 i - 1 位置指向的next数组的 前缀的 下一个元素的 next数组的位置

    然后比较它的下一个元素再与 i - 1位置的元素比较,如果相等,则为它的next数组 + 1,否则

    重复上面的步骤,当找的位置没有前缀时,那么 i 位置的next数组的值为0

    next数组

     private static int[] nextArray(String str2) {
            if(str2 == null || str2.length() == 0) return null;
    
            int[] next = new int[str2.length()];
            next[0] = -1;
            next[1] = 0;
    
            int num = 0;
            int index = 2;
            while(index < str2.length()){
                if(str2.charAt( num ) == str2.charAt( index - 1 )) {
                    next[index++] = ++num;
                } else if(num > 0) {
                    num = next[num];
                }if(num <= 0) {
                    next[index++] = 0;
                    num = 0;
                }
            }
            return next;
        }
    

      

    整体实现

    public class KMP {
        public static int kmp(String str1, String str2){
            if(str1 == null || str1.length() == 0) return -1;
            int[] next = nextArray(str2);
            int i = 0;
            int j = 0;
            while(i < str1.length() && j < str2.length()){
                if(str1.charAt( i ) == str2.charAt( j )){
                    i++;
                    j++;
                } else{
                    j = next[j];
                }
                if(j == -1){
                    i++;
                    j++;
                }
            }
            if(j == str2.length()) return i - j;
            return -1;
        }
    
        private static int[] nextArray(String str2) {
            if(str2 == null || str2.length() == 0) return null;
    
            int[] next = new int[str2.length()];
            next[0] = -1;
            next[1] = 0;
    
            int num = 0;
            int index = 2;
            while(index < str2.length()){
                if(str2.charAt( num ) == str2.charAt( index - 1 )) {
                    next[index++] = ++num;
                } else if(num > 0) {
                    num = next[num];
                }if(num <= 0) {
                    next[index++] = 0;
                    num = 0;
                }
            }
            return next;
        }
        public static void main(String[] args){
            int num = kmp( "abcabcababaccc", "ababa" );
            System.out.println(num);
        }
    }
    

      

  • 相关阅读:
    Flink实时数仓(数据可视化)
    Hive调优
    面试(涉及技术一)
    启动Flink的yarnsession模式出错
    面试(涉及技术二)
    Filnk实时数仓(DWS层)
    Filnk实时数仓(Clickhouse)
    Filnk实时数仓(Prometheus监控)
    Filnk实时数仓(DWM层)
    Centos7下杀毒软件clamav的安装和使用
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8982915.html
Copyright © 2011-2022 走看看