zoukankan      html  css  js  c++  java
  • KMP算法代码

    public class KMP {
    
        public static void main(String[] args) {
            KMP kmp = new KMP();
            Integer[] match = kmp.match("aacaabaabaac", "aabaa");
            System.out.println(Arrays.toString(match));
        }
    
        public int[] getMatchLength(String pattern) {
            int matchLength = 0;
            // maxLength表示长度为i的字符串前缀和后缀的最长公共部分,i从1开始,maxLength[0]和maxLength[1]都为0
            int[] maxLength = new int[pattern.length() + 1];
            // index+1是当前得字符串长度,寻找字符串的前缀和后缀公共部分的最大长度
            for (int index = 1; index < pattern.length(); index++) {
                // 如果index位置的字符和matchLength位置的字符不相同,matchLength退化为长度为matchLength的字符串的最大公共长度
                while (matchLength > 0 && pattern.charAt(matchLength) != pattern.charAt(index))
                    matchLength = maxLength[matchLength];
                // 如果index位置的字符和matchLength位置的字符相同,matchLength长度加1,否则matchLength会为0
                // 初始状态以及上面的公共序列长度发现过程,会保证matchLength为0
                if (pattern.charAt(matchLength) == pattern.charAt(index))
                    matchLength++;
                // index+1长度的字符串,前缀和后缀公共部分的最大长度未matchLength
                maxLength[index + 1] = matchLength;
            }
    
            return maxLength;
        }
    
        public Integer[] match(String source, String pattern) {
            int[] matchLength = getMatchLength(pattern);
            int sourceIndex = 0, patternIndex = 0;
            List<Integer> matchIndex = new LinkedList<Integer>();
            for (; sourceIndex < source.length(); sourceIndex++) {
                // 如果sourceIndex和patternIndex位置的字符不相同,patternIndex退化为,pattern中从起始位置开始、长度为patternIndex的字符串的最大公共长度,直到为0
                while (patternIndex > 0 && source.charAt(sourceIndex) != pattern.charAt(patternIndex)) {
                    patternIndex = matchLength[patternIndex];
                }
                // 如果soruceIndex位置和patternIndex位置的字符相等,patternIndex增加1
                if (patternIndex < pattern.length() && source.charAt(sourceIndex) == pattern.charAt(patternIndex)) {
                    patternIndex++;
                }
                // 如果patternIndex为pattern的长度,则发现一个匹配,保存sourceIndex的位置信息,同时patternIndex退化为,pattern中从起始位置开始、长度为patternIndex的字符串的最大公共长度
                if (patternIndex == pattern.length()) {
                    matchIndex.add(sourceIndex - pattern.length() + 1);
                    patternIndex = matchLength[patternIndex];
                }
            }
            Integer[] arrays = new Integer[0];
            return matchIndex.toArray(arrays);
        }
    }

    通过对pattern中,从起始位置开始,长度为i的字符串,进行前缀、后缀最大公共长度进行计算,可在后续的字符串匹配时减少不必要的操作。、

    设:原始字符串为srouce,模式字符串为pattern

    使用数组matchLength保存最大公共长度值,matchLength的长度为pattern.length()+1。如果matchLength[10]为3,表示pattern[0:10-1]的最大公共长度为3。

    在计算前后缀的最大公共长度时,发现长度为a的字符串的最大公共长度为matchLength[a],设为x,即pattern[0:a-1]中,pattern[0:x-1]==pattern[a-x:a-1]。

    计算长度为a+1的字符串的最大公共长度时,可启发式的基于长度为a的字符串的计算结果,如果pattern[(x-1)+1]==pattern[(a-1)+1],则长度为a+1的字符串的最大公共长度为x+1。

    否则继续基于长度为x(matchLength[a])的字符串的计算结果,进行计算,直到x为0。长度为x的字符串的最大公共长度,为matchLength[x]。

    通过以上方式可以计算出matchLength的各项数值,并在source中匹配pattern时,减少不必要的操作。

  • 相关阅读:
    chrome——关于chrome浏览器的奇葩问题
    vscode——配置终端集成bash和cmd
    AndroidStudio——Android SDK
    Navicat——如何导出所有的查询数据
    mpvue——实现点击数组内的某一元素进行置顶(排序第一)操作
    TP5.x——开启跨域访问
    TP5.x——聊天列表查询
    MarkDowm——语法篇
    写一个整数四则运算的解析器——语法分析部分
    写一个整数四则运算的解析器——词法分析部分
  • 原文地址:https://www.cnblogs.com/mahuan2/p/6373572.html
Copyright © 2011-2022 走看看