首页 > 其他分享 >查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串

查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串

时间:2023-09-11 15:35:20浏览次数:32  
标签:子串 String int pos length 字符串 strB strA 最长

要求

给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。

输入描述

命令行工具接收两个字符串参数。输入字符串的合法字符集为[a-zA-Z0-9],大小写敏感,无需考虑异常输入场景。

输出描述

输出一行最长公共子串

示例

输入
1ABCD2345G 12345EF

输出
2345

解法一:滑动窗口法

滑动窗口法可以看成两列火车,一列静止一列逐步向前行驶。

查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串_字符串

将字符串长度较短的strA看作上面的静止列车,字符串较长的strB看作下面滑动的列车,strB经过strA一共分为三个阶段:

①B的火车头进入A,一直往右边移动 但火车头没有离开A

查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串_字符串_02

②B火车头跑出出了A,火车尾还没有进入A

查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串_最长公共子串_03

③B火车尾进入A,继续往前开,但是火车尾还没有离开A

查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串_最长公共子串_04

public String findCommonSubStr(String strA, String strB) {
        //一定要先明确strA和strB哪个长哪个短
        return strA.length() < strB.length() ? findMax(A, strB) : findMax(strB, A);
    }

    //strA串的长度较小, strB串的长度较大
    String findMax(String strA, String strB) {
        String result = "";
        String maxStr = "";
       //B的火车头进入A,一直往右边移动 但火车头没有离开A
        for (int len = 1; len <= strA.length(); len++) {
            maxStr = maxStr(strA, 0, strB, strB.length() - len, len);
            if (maxStr.length() > result.length()) {
                result = maxStr;
            }
        }
        // B火车头跑出了A,火车尾还没有进入A
        for (int j = strB.length() - strA.length(); j >= 0; j--) {
            maxStr = maxStr(strA, 0, strB, j, strA.length());
            if (maxStr.length() > result.length()) {
                result = maxStr;
            }
        }
        //B火车尾进入A,继续往前开,但是火车尾还没有离开A
        for (int i = 1; i < strA.length(); i++) {
            maxStr = maxStr(strA, i, B, 0, strA.length() - i);
            if (maxStr.length() > result.length()) {
                result = maxStr;
            }
        }
        return result;
    }

    //strA子串从i位置和strB子串的j位置对齐,然后开始从头一一比对各个字符是否相同
    // len参数是指比对的最大长度
    String maxStr(String strA, int i, String strB, int j, int len) {
        int count = 0, max = 0;
        int pos = 0;
        for (int k = 0; k < len; k++) {
            if (strA.charAt(i + k) == strB.charAt(j + k)) {
                count++;
            } else if (count > 0) {
                if (count > max) {
                    max = count;
                    pos = j + k;
                }
                count = 0;
            }
        }
        //在上面的for循环中,当k=len-1时,count可能也++了,所以下面的代码还要做个特殊判断
        if (count > 0 && count > max) {
            max = count;
            pos = j + len;
        }
        return strB.substring(pos - max, pos);
    }

解法二:动态规划

dp[i][j]表示nums1[i...end]与nums2[j...end]的最长公共前缀部分的长度

如果 nums1[i] == nums2[j],那么 dp[i][j] = dp[i + 1][j + 1] + 1

如果 nums1[i] != nums2[j],那么前缀部分肯定是不相同的,所以 dp[i][j] = 0

在这个过程中记录下dp数组的最大值即可,即 res

因为dp[i][j]是从dp[i + 1][j + 1]转移而来的,所以要倒着遍历数组

public String findCommonSubStr(String str1, String str2) {
        int str1lenth = str1.length(), str2lenth = str2.length();
        int[][] dp = new int[str1lenth + 1][str2lenth + 1];
        int maxLength = 0; //公共子串的最大长度
        int pos = -1;//因为我们的最长公共子串是从s2中截取的,所以这里用pos来标识s2中公共子串的结束位置索引
        for (int i = str1lenth - 1; i >= 0; i--) {
            for (int j = str2lenth - 1; j >= 0; j--) {
                dp[i][j] = str1.charAt(i) == str2.charAt(j) ? dp[i + 1][j + 1] + 1 : 0;
                if (dp[i][j] > maxLength) {
                    maxLength = dp[i][j];
                    pos = j;
                }
            }
        }
        return str2.substring(pos, pos + maxLength);
    }

解法三:二维数组划“捺”法

将两个数组看成二维数组的样式,从右上角点开始,划“捺”,定义出发点,出发点一开始时(0,m-1),出发点向左移动,一直移动到左上角以后,开始从左上角往左下角向下移动

查找字符串最长公共子串,请编码实现一个命令行工具,找出指定的2个字符串的最长公共子串_字符串_05

import java.io.*;
 
public class Main{
    public static void main(String[] args)throws IOException{
        BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
        String s1 = read.readLine();
        String s2 = read.readLine();
        int n = s2.length();
        int m = s1.length();
        int col = m-1;//出发点的列
        int row = 0;//出发点的行
        int max=0;//最大长度
        int pos = -1;//因为我们的最长公共子串是从s2中截取的,所以这里用pos来标识s2中公共子串的结束位置索引
        while(col!=0 || row < n){
        //初始化 i,j
            int i = row;
            int j = col;
            int len = 0;
            while(i<n && j<m){//划“捺”,这里的while()里面的限制就是为了不让划“捺”划到超出整个棋盘
                if(s1.charAt(j) == s2.charAt(i)){
                    len++;
                    if(len>max){
                        max = len;
                        pos = i;
                    }
                    
                }else{
                    len=0;
                }
                i++;
                j++;
            }
            if(col == 0){//如果出发点已经移到了最左边了,那就只能向下方移动了
                row++;
            }else{ //如果没有移到最左边,那就继续往左边移动
                col--;
            }
        }
        String str = s2.substring(pos-max+1,pos+1);
        if(str.length()==0){
            str = "-1";
        }
        System.out.println(str);
    }
}

标签:子串,String,int,pos,length,字符串,strB,strA,最长
From: https://blog.51cto.com/u_16244372/7436125

相关文章

  • Golang 初识: 函数调用与定义丶字符串处理丶Json的处理
    一.基本函数调用与定义1packagemain23import(4"encoding/json"5"errors"6"fmt"7"math/rand"8"mylib/pkg/student"9"mylib/pkg/utils"10"sort"11......
  • 字符串减法
    字符串减法1.题目地址https://www.acwing.com/problem/content/1536/2.题目解析具体题意,看上图即可。这里不再赘述。值得注意的是:这道题对于时间复杂度的要求很高,需要考虑优化问题。3.题解4.代码......
  • Java基础学习——字符串
    目录1String概述 2String构造方法代码实现和内存分析2.1创建方式2.2内存区1.StringTable(串池)2.直接赋值创建字符串方式内存图3.通过new创建字符串方式内存图 3字符串比较3.1“==”号比较的内容    1String概述总结:1.String是Java定义好......
  • 较真:js判断中文字符串长度的正确方法
    对于使用javascript编程的人来说,判断字符串长度应该是常用又简单的操作,但在判断包含有中文字符或其他非asci字符的字符串长度时,却有些坑在里面。错误做法1先看看最常用的做法,也就是使用String.length判断:letstr="你好奥";letlen=str.length;console.log(len);//打印出来......
  • 【Python基础】字符串常用方法
    replace()方法replace()方法把字符串中的old(旧字符串)替换成new(新字符串),如果指定第三个参数max,则替换不超过max次。str="ThisisATest"print(str.replace("is","was"))#ThwaswasATest"print(str.replace("is","was",1))#Thwas......
  • java 字符串常用API
      importjava.util.Scanner;publicclassMain{publicstaticvoidmain(Stringargs[]){Scannersc=newScanner(System.in);Strings="1233.32";doubley=Double.parseDouble(s);//将一个字符串强制转化为浮点数Stri......
  • 字符串哈希
    字符串哈希可以快速判断字符串是否相同(比KMP还快)字符串前缀哈希法先预处理出来所有前缀的哈希str="ABCDEFGHI";h[0]=0;h[1]="A";//哈希值h[2]="AB";h[3]="ABC";h[4]="ABCD";...求字符串哈希值的方法是将字符串看成一个p进制的数:"ABCD"第一位的数是:A-......
  • 205. 同构字符串
    给定两个字符串 s 和 t ,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本......
  • 初识python--python中的字符串
    python中的字符串1、字符串的定义与访问字符串的定义字符串是一种常见的数据类型=>数据容器的一种,一个变量中可以同时保存多个字符基本语法:使用双引号(三引号的形式支持字符串的换行)变量名称='字符串'变量名称="字符串"#三引号变量名称=''' 锄禾日当午, 汗滴......
  • js json用法 转json字符串 json对象( 重点看最后)
    jsjson:JSON.parse() //转为json对象。JSON.stringify() //转为JSON字符串。举例:<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>jsjson举例</title></head><body><pid="demo"></p&g......