字符串匹配

模板:

KMP:

细节在代码中

看不懂的可以参照:如何更好地理解和掌握 KMP 算法? - 阮行止的回答 - 知乎
https://www.zhihu.com/question/21923021/answer/1032665486

package StringMatch.KMP;

import java.util.ArrayList;
import java.util.List;

public class KMP {

    /**
     * 计算p在s中所有匹配子串的开始位置
     * @param s 主串
     * @param p 模式串
     * @return 所有匹配子串的开始位置
     */
    public List search(String s,String p){
        ArrayList ans = new ArrayList<>();
        char[] sch = s.toCharArray();
        char[] pch = p.toCharArray();
        int[] next = buildNext(p);

        int count = 0;
        for (int i = 0; i < sch.length; i++) {
            while(count > 0 && pch[count] != sch[i]){
                // 回退到上一轮可以复用的前缀的长度
                count = next[count-1];
            }

            if( pch[count] == sch[i]){
                count++;
            }

            if(count == pch.length){
                ans.add(i-pch.length+1);
                // 复用整个模式串的k-前/后缀长度
                count = next[count-1];
            }
        }

        return ans;
    }

    private int[] buildNext(String p){
        char[] ch = p.toCharArray();
        int plen = ch.length;
        int[] next = new int[plen];
        /*
        注意next[i]的值不可能是i+1,选取整个子串对跳过失败位置没有任何帮助
        例如abcabcd,匹配到d错了,此时看前方next[5]=3,即前五位正确,并且3前缀=3后缀
        然后向后挪动三位 也就是用第二个abc去匹配第一个abc
        但如果选取整个子串 next[5] = 6,这样向后挪动6位,就从d那一位开始匹配了
        反而错过了第二个abc,导致可能的错误
         */
        next[0] = 0;
        for(int i=1;i

1. LC 3008 找出数组中的美丽下标Ⅱ

思路比较简单:

  1. KMP找出所有匹配的a模式串开始索引
  2. … b模式串 …
  3. 由于KMP查找是顺序的,所以索引也是顺序的,对于任意一个index∈kmp(a),对kmp(b)二分查找即可

这道题就是教kmp板子的(周赛的时候不会板子直接T了捏

import java.util.ArrayList;
import java.util.List;

class Solution {
    static int interval;
    public List beautifulIndices(String s, String a, String b, int k) {
        interval = k;
        char[] sch = s.toCharArray();
        char[] ach = a.toCharArray();
        char[] bch = b.toCharArray();
        ArrayList ans = new ArrayList<>();
        List ares = kmp(sch, ach);
        List bres = kmp(sch, bch);
        if(bres.isEmpty()){
            return ans;
        }
        for (Integer num : ares) {
            int bs = bs(num, bres);
            if(check(bs,num)){
                ans.add(num);
            }
        }
        return ans;
    }

    private int bs(int index,List bres){
        int lp,rp,mid,ans;
        lp = 0;
        rp = bres.size();
        ans = -interval-1;
        while(lp>>1)+lp;
            Integer num = bres.get(mid);
            ans = Math.abs(num-index) kmp(char[] sch,char[] pch){
        ArrayList ans = new ArrayList<>();
        int[] next = buildNext(pch);

        int count = 0;
        for (int i = 0; i < sch.length; i++) {
            while(count > 0 && pch[count] != sch[i]){
                count = next[count-1];
            }

            if( pch[count] == sch[i]){
                count++;
            }

            if(count == pch.length){
                ans.add(i-pch.length+1);
                count = next[count-1];
            }
        }

        return ans;
    }

    private int[] buildNext(char[] pch){
        int[] next = new int[pch.length];
        next[0] = 0;
        for(int i=1;i

你可能感兴趣的:(数据结构与算法,java,算法,leetcode)