• [leetCode]14.最长公共子串


    在这里插入图片描述

    解法一: 横向扫描(暴力匹配)

    可以使用第一个字符串与第二个字符串进行最长公共子串的匹配,再用这个最长公共子串和后面的字符串进行匹配,如果匹配到的子串为空,则最长公共子串一定为空。

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(strs == null || strs.length == 0) {
                return "";
            }
            String prefix = strs[0];
            for(int i = 1; i < strs.length; i++){
                prefix = longestCommonPrefix(prefix, strs[i]);
                if(prefix.length() == 0)break;
            }
            return prefix;
        }
        public String longestCommonPrefix(String prefix, String str){
            int index = 0;
            int length = Math.min(prefix.length(), str.length());
            while(index < length && prefix.charAt(index) == str.charAt(index)){
                index++;
            }
            return prefix.substring(0,index);
        }
    }
    

    解法二 分治

    主要思想:把字符串数组分为左右两个子问题,分别进行求解,再求两个子问题解的最长前缀。
    在这里插入图片描述

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(strs == null || strs.length == 0) return "";
            return longestCommonPrefix(strs,0,strs.length-1);
        }
    
        public String longestCommonPrefix(String[] strs, int start, int end){
            if(start == end){//如果分解到只剩一个字符串则返回这个字符串
                return strs[start];
            }else{
                int mid = (end - start)/2 +start;
                String leftLCP = longestCommonPrefix(strs,start, mid);
                String rightLCP = longestCommonPrefix(strs,mid + 1, end);
                return commonPrefix(leftLCP, rightLCP);
            }
        }
    
        public String commonPrefix(String l, String r){
            int index = 0;
            int len = Math.min(l.length(), r.length());
            while(index < len && l.charAt(index) == r .charAt(index)){
                index++;
            }
            return l.substring(0,index);
        }
    }
    

    解法三 二分查找法

    字符串数组的最大前缀由字符串数组中的最短字符串决定因此

    • 先计算最短字符串的长度
    • 对字符数组第一个字符串进行二分查找
      如果前半部分属于最长前缀则丢弃前半部分,继续查找后半部分
      如果前半部分不属于前缀,则丢弃后半部分,继续查找前半部分
    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(strs == null || strs.length == 0) return "";
            int minLen = strs[0].length();//最短字符串的长度
            for(String each : strs){
                minLen = each.length() < minLen ? each.length() : minLen;
            }
            int low = 0, high = minLen;
    
            while(low <= high){
                int mid = (low + high)/2;
                if(isCommonPrefix(strs,mid)){
                    low = mid + 1;
                }else{
                    high = mid -1;
                }
            }
            return strs[0].substring(0,(low + high)/2);
        }
    
        public boolean isCommonPrefix(String[] strs, int mid){
            String subStr = strs[0].substring(0,mid);
            for(int i = 0; i < strs.length; i++){
                for(int j = 0; j < subStr.length(); j++){
                    if(strs[i].charAt(j) != subStr.charAt(j))return false;
                }
            }
            return true;
        }
    }
    

    解法四 纵向扫描

    在这里插入图片描述

    • 字符串数组左对齐按行排列
    • 按列纵向进行遍历判断下一个字符串第i列的字符是否等于第一行第i列的字符
      如果不相等则返回子串
      如果i等于当前行的长度则返回子串
    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(strs == null || strs.length == 0) return "";
            int length = strs[0].length();
            int count = strs.length;
            for(int i = 0; i < length; i++){
                char c = strs[0].charAt(i);
                for(int j = 1; j < count; j++){
                    if(strs[j].charAt(i)!=c || strs[j].length() == i){
                        return strs[0].substring(0,i);
                    }
                }
            }
            return strs[0];
        }
    }
    

    参考

    https://leetcode-cn.com/problems/longest-common-prefix/solution/zui-chang-gong-gong-qian-zhui-by-leetcode-solution/

  • 相关阅读:
    【BZOJ-4423】Bytehattan 并查集 + 平面图转对偶图
    【BZOJ-2251】外星联络 后缀数组 + 暴力
    【BZOJ-1046】上升序列 DP + 贪心
    【BZOJ-3667】Rabin_Miller算法 随机化判素数
    【BZOJ-4173】数学 欧拉函数 + 关于余数的变换
    【BZOJ-1692&1640】队列变换 后缀数组 + 贪心
    【BZOJ-1857】传送带 三分套三分
    【BZOJ-1717】Milk Patterns产奶的模式 后缀数组
    【训练记录】后缀数组
    【BZOJ-1031】字符加密Cipher 后缀数组
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13860031.html
Copyright © 2020-2023  润新知