美文网首页
左神算法笔记——KMP衍生题

左神算法笔记——KMP衍生题

作者: yaco | 来源:发表于2020-04-08 13:56 被阅读0次

题目一

给定一个字符串str,向字符串尾部添加字符,使得添加结束后的字符串包含两个原始字符串str。
问:满足结束条件的最小添加步数,一次只能添加一个元素

分析

这题可以用KMP算法中求解字符串m的preNextArr数组的方式解决。

  • 如: aba字符串,3位置的最长公共前后缀的长度为1,所以只需要构成字符串ababa,也就时目前已经存在了1个已有的字符a,只要加上从开始位置的1一直到字符串结束的字符就可以了。
  • 如:abcabc字符串,最后一位的最长公共前后追的长度为3,如果只需要在后面加上 6 - 3 = 3位即可,构成abcabcabc

代码

    // 获取最少的操作步骤————京东面试题
    public static int getMinStep(String s) {
        // 首先操作的字符串不可以为null
        if(s == null || "".equals(s)) {
            throw new RuntimeException("输入参数有误!");
        }
        int len = s.length();
        // 边界条件判断
        if(len == 1) return 1;
        if(len == 2) return s.charAt(0) == s.charAt(1) ? 1 : 2;
        //将s字符串转化为字符数组进行KMP思想求解
        char[] chars = s.toCharArray();
        return len - getPreNextStep(chars);
    }

    public static int getPreNextStep(char[] chars){
        int[] next = new int[chars.length + 1];
        next[0] = -1;
        next[1] = 0;
        int pos = 2;
        int pre = 0;
        while(pos < next.length){
            if(chars[pos - 1] == chars[pre]){
                next[pos++] = ++pre;
            }else if(pre > 0){
                // 还可以继续跳
                pre = next[pre];
            }else{
                next[pos++] = 0;
            }
        }
        return next[next.length - 1];
    }

    public static void main(String[] args) {
        String s = "abcabc";
        System.out.println(getMinStep(s));
    }

题目二

给定两个头节点t1和t2,请你判断两个树是否为包含关系,即其中一个树是另一个树的子树。

思路

  • 首先将两个树分别按照前序遍历的顺序进行序列化,
  • 之后就是标准的KMP求解问题,检查t1序列化之后的字符串s1中是否包含t2序列化之后的字符串s2,如果有,则返回true,否则返回false。

代码

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    public static boolean isSubtree(Node t1, Node t2) {
        String t1Str = serialByPre(t1);
        String t2Str = serialByPre(t2);
        return getIndexOf(t1Str, t2Str) != -1;
    }

    public static String serialByPre(Node head) {
        if (head == null) {
            return "#!";
        }
        String res = head.value + "!";
        res += serialByPre(head.left);
        res += serialByPre(head.right);
        return res;
    }

    // KMP
    public static int getIndexOf(String s, String m) {
        if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
            return -1;
        }
        char[] ss = s.toCharArray();
        char[] ms = m.toCharArray();
        int[] nextArr = getNextArray(ms);
        int index = 0;
        int mi = 0;
        while (index < ss.length && mi < ms.length) {
            if (ss[index] == ms[mi]) {
                index++;
                mi++;
            } else if (nextArr[mi] == -1) {
                index++;
            } else {
                mi = nextArr[mi];
            }
        }
        return mi == ms.length ? index - mi : -1;
    }

    public static int[] getNextArray(char[] ms) {
        if (ms.length == 1) {
            return new int[] { -1 };
        }
        int[] nextArr = new int[ms.length];
        nextArr[0] = -1;
        nextArr[1] = 0;
        int pos = 2;
        int cn = 0;
        while (pos < nextArr.length) {
            if (ms[pos - 1] == ms[cn]) {
                nextArr[pos++] = ++cn;
            } else if (cn > 0) {
                cn = nextArr[cn];
            } else {
                nextArr[pos++] = 0;
            }
        }
        return nextArr;
    }

    public static void main(String[] args) {
        Node t1 = new Node(1);
        t1.left = new Node(2);
        t1.right = new Node(3);
        t1.left.left = new Node(4);
        t1.left.right = new Node(5);
        t1.right.left = new Node(6);
        t1.right.right = new Node(7);
        t1.left.left.right = new Node(8);
        t1.left.right.left = new Node(9);

        Node t2 = new Node(2);
        t2.left = new Node(4);
        t2.left.right = new Node(8);
        t2.right = new Node(5);
        t2.right.left = new Node(9);

        System.out.println(isSubtree(t1, t2));
    }

相关文章

  • 左神算法笔记——KMP衍生题

    题目一 给定一个字符串str,向字符串尾部添加字符,使得添加结束后的字符串包含两个原始字符串str。问:满足结束条...

  • 左神算法笔记——KMP算法

    介绍 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,...

  • KMP 专题整理

    KMP 学习记录 kuangbin专题十六——KMP KMP 学习总结 朴素 KMP 算法 拓展 KMP 算法(E...

  • 对KMP算法的一些理解

    最近学到KMP算法,下面讲讲对KMP算法的一些个人理解,希望对大家有帮助! 对于KMP算法的理解: 整个KMP算法...

  • KMP算法文章合集

    字符串的查找:朴素查找算法和KMP算法 暴力匹配算法与KMP算法(串的匹配) 字符串查找算法BF和KMP 字符串匹...

  • 串的模式匹配算法

    KMP算法 算法匹配

  • 问答|KMP算法学习笔记

    问题 目录KMP是什么,做什么用的KMP算法的高效体现在哪如何KMP算法的next数组KMP的代码KMP的时间复杂...

  • KMP算法——寻找子串位置

    KMP算法——寻找子串位置 1、KMP算法简介: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J....

  • 算法笔记-KMP算法

    整理了一下据说由于过于晦涩难懂而导致某系统程序猿直接在实现字符串匹配的时候直接用暴力算法代替的KMP算法,初看之时...

  • 字符串匹配 - KMP算法

    前面我们介绍非常高效的 BM 算法,今天我们介绍另一个非常出名且高效的 KMP 算法。 KMP 算法思想 KMP ...

网友评论

      本文标题:左神算法笔记——KMP衍生题

      本文链接:https://www.haomeiwen.com/subject/ldctmhtx.html