*65 /70 查找两个字符串a,b中的最长公共子串

题目描述
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
输入描述:
输入两个字符串
输出描述:
返回重复出现的字符
示例1
输入
abcdefghijklmnop
abcsafjklmnopqrstuvw
输出
jklmnop

while True:
    try:
        str1=input()
        str2=input()
        n = 0
        s = ''
        if len(str1)>len(str2):
            str1,str2 = str2, str1
        for i in range(len(str1)+1):
            if str1[i-n:i] in str2:
                s = str1[i-n:i]
                n +=1
        print(s)
    except:
        break

最长公共子串,长度

while True:
    try:
        str1=input()
        str2=input()
        n = 0
        s = ''
        if len(str1)>len(str2):
            str1,str2 = str2, str1
        for i in range(len(str1)+1):
            if str1[i-n:i] in str2:
                s = str1[i-n:i]
                n +=1
        print(n)
    except:
        break
def getCommonStr(str1,str2):
    n=len(str1)
    for i in range(n):#每次递减长度
        start=0
        end=n-i
        while(end<=n):
            if str1[start:end] in str2:
                return len(str1[start:end])
            else:
                start+=1
                end+=1
    return 0
while True:
    try:
        a = str(input())
        b = str(input())
        if len(a)>len(b):
            a,b=b,a
        print(getCommonStr(a,b))
    except:
        break

java
最长公共子串
在这里插入图片描述

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        while(in.hasNext()){
            String str1=in.nextLine();
            String str2=in.nextLine();
            if (str1.length()<str2.length()){
                System.out.println(getCommonStr(str1,str2));
            }
            else
                System.out.println(getCommonStr(str2,str1));
        }
    }
    public static String getCommonStr(String sstr,String lstr){
    	if(sstr==null || lstr==null) return "";
    	if(sstr.equals(" ") || lsstr.equals(" ")) return " ";
        for(int i=0;i<sstr.length();i++){//每次字符串递减的长度
            for(int start=0,end=sstr.length()-i;end<=sstr.length();start++,end++){//start,end头尾指针,不断后移,直到end为最后一个index+1
                String temp=sstr.substring(start,end);
                if (lstr.contains(temp)){
                    return temp;
                }
            }
        }
        return " ";
    }
}

每次子串长度递减,从0-len-1
在该长度时,定义首位指针,进行移动判断改子串是否被长串包含

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        while(in.hasNext()){
            String str1=in.nextLine();
            String str2=in.nextLine();
            if (str1.length()<str2.length()){
                System.out.println(getCommonStr(str1,str2));
            }
            else
                System.out.println(getCommonStr(str2,str1));
        }
    }
    public static int getCommonStr(String sstr,String lstr){
        for(int i=0;i<sstr.length();i++){//每次字符串递减的长度,遍历短的字符串
            for(int start=0,end=sstr.length()-i;end<=sstr.length();start++,end++){//start,end头尾指针,不断后移,直到end为最后一个index+1
                String temp=sstr.substring(start,end);
                if (lstr.contains(temp)){
                    return temp.length();
                }
            }
        }
        return 0;
    }
}

动态规划

// 动态规划 复杂度o(n1*n2)
// memo[i][j]存放第一个str1以第i-1个字符为结尾的子串(必须用到) 和str2以第j-1个字符作为结尾的子串(必须用到)
// 的最大公共连续子串长度
// 输出时按照先遍历二维数组的长边 再遍历二维数组的短边 查找最大长度 以及对应的 结尾下标
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s1 = br.readLine();
        char[] str1 = s1.toCharArray();
        char[] str2 = br.readLine().toCharArray();
        br.close();
        int n1 = str1.length, n2 = str2.length;
        int max = -1, index = 0;
        int[][] memo = new int[n1+1][n2+1];
        for(int i = 1; i <= n1; i++)
            for(int j = 1; j <= n2; j++)
                if(str1[i-1] == str2[j-1])
                    memo[i][j] = memo[i-1][j-1] +1;
        if(n1 <= n2){
            for(int j = 1; j <= n2; j++)
                for(int i = 1; i <= n1; i++)
                    if(memo[i][j] > max){
                        max = memo[i][j];
                        index = i;
                    }
        }else{
            for(int i = 1; i <= n1; i++)
                for(int j = 1; j <= n2; j++)
                    if(memo[i][j] > max){
                        max = memo[i][j];
                        index = i;
                    }
        }
        System.out.println(s1.substring(index-max,index));
    }
}

思路:dp[i][j]表示str1[0…i]与str2[0…j]的最长公共子串的长度
如果 str1 的长度为 N,str2 的长度为 M,生成大小为 N*M 的 数组 dp , dp[i][j]表示 str1[0…i] 与 str2[0…j] 的

最长公共子串的长度。

计算dp[i][j] 的方法如下:

矩阵 dp 的第一列 dp[0…m-1][0].对于 某个位置(i,0)如果str1[i]==str2[0],则dp[i][0]=1,否则dp[i][0]=0
矩阵 dp 的第一行 dp[0][0…n-1].对于 某个位置(0,j)如果str1[0]==str2[j],则dp[0][j]=1,否则dp[0][j]=0
其他位置从左到右从上到下计算,dp[i][j]的值只有两种情况:
1). str1[i]==str2[j],dp[i][j]=dp[i-1][j-1]+1;

2). tr1[i]!=str2[j]则dp[i][j]=0;

str1=”abc”,str2=”caba”的 dp 矩阵如下:

a  b  c
1
c  0  0  1

a  1  0  0

b  0  2  0

a  1  0  0
短字串sstr为行str1,长字串lstr为列str2
重要

    public static int getCommonStr(String sstr,String lstr){
        int len1=sstr.length();
        int len2=lstr.length();
        int[][] dp=new int[len1][len2];
        int max=0;
        //第一列赋值,判断sstr中第一个字符是否在lstr中出现
        for(int i=0;i<len1;i++){
            if (sstr.charAt(i)==lstr.charAt(0)){
                dp[i][0]=1;
            }
            else
                dp[i][0]=0;
        }
        //第一行赋值,判断llstr中第一个字符是否在sstr中出现
        for(int j=0;j<len2;j++){
            if (lstr.charAt(j)==sstr.charAt(0)){
                dp[0][j]=1;
            }
            else
                dp[0][j]=0;
        }
        for(int i=1;i<len1;i++){
            for(int j=1;j<len2;j++){
                if(sstr.charAt(i)==lstr.charAt(j)){
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else
                    dp[i][j]=0;//区别最长子序列
                if(dp[i][j]>max)
                    max=dp[i][j];
            }
        }
        return max;
    }
}

或者在字符串前各加一个空字符,初始化dp[len1+1][len2+1]

import java.util.Scanner;
public class Main {
    public static void commenSub(String s1,String s2){
        s1=" "+s1;//相当于初始化a[0]=0;a[1]~a[m-1]=s1;
        s2=" "+s2;
        char a[]=s1.toCharArray();
        char b[]=s2.toCharArray();
        int m=a.length;
        int n=b.length;
        int c[][]=new int[m][n];
        int max=0;
        //没有初始化
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                if(a[i]==b[j]){//相等
                    c[i][j]=c[i-1][j-1]+1;
                }else{//不等
                    c[i][j]=0;
                }
                if(max<c[i][j]){max=c[i][j];}//记录最长字串
            }
        }
        System.out.println(max);
    }
    public static void main(String args[]){
     Scanner sc=new Scanner(System.in);
         while(sc.hasNext()){
            String s1=sc.next();
            String s2=sc.next();
            commenSub(s1,s2);
        }
    }
}

或者在字符串前各加一个空字符,初始化dp[len1+1][len2+1]
在这里插入图片描述

dp[len1+1][len2+1]的方法:dp[i][j]表示str1的前i个字符串与str2的前j个字符串,此时字符索引为i-1,j-1;最后一个为dp[len1][len2]表示str1的所有len1个字符串与str2的所有len2个字符串

 public static int getCommonStrLength(String str1, String str2){
         
    int len1 = str1.length();
    int len2 = str2.length();
    int[][] dp = new int[len1+1][len2+1];
     
    for(int i=0;i<=len1;i++){
        for(int j=0;j<=len2;j++){
            dp[i][j] = 0; ?
        }
    }
     
    for(int i=1;i<=len1;i++){
        for(int j=1;j<=len2;j++){
            if(str1.charAt(i-1) == str2.charAt(j-1)){?为什么判断前一个
                dp[i][j] = dp[i-1][j-1] + 1;
            }else{
                dp[i][j] = 0;   //区别在这儿        
            }
        }
    }
     
    int max = 0;
    for(int i=0;i<=len1;i++){
        for(int j=0;j<=len2;j++){
            if(max < dp[i][j])
                max = dp[i][j];
        }
    }
     
    return max;
}

}

最长公共序列
最长公共子序列是:
dp[i][j] – 表示子串str1[0…i]和子串str[0…j]的最长公共子序列
当str1[i] == str2[j]时,dp[i][j] = dp[i-1][j-1] + 1;
否则,dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
最优解为dp[len1-1][len2-1];

或者dp[len+1][len+2]的方法

 public static int getCommonStr(String sstr,String lstr){
        int len1=sstr.length();
        int len2=lstr.length();
        int[][] dp=new int[len1][len2];
        int max=0;
        //第一列赋值,判断sstr中第一个字符是否在lstr中出现
        for(int i=0;i<len1;i++){
            if (sstr.charAt(i)==lstr.charAt(0)){
                dp[i][0]=1;
            }
            else
                dp[i][0]=0;
        }
        //第一行赋值,判断llstr中第一个字符是否在sstr中出现
        for(int j=0;j<len2;j++){
            if (lstr.charAt(j)==sstr.charAt(0)){
                dp[0][j]=1;
            }
            else
                dp[0][j]=0;
        }
        for(int i=1;i<len1;i++){
            for(int j=1;j<len2;j++){
                if(sstr.charAt(i)==lstr.charAt(j)){
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);//区别
            }
        }
        return dp[len1-1][len2-1];
    }
}

public static int getCommonStrLength(String str1, String str2){
         
        int len1 = str1.length();
        int len2 = str2.length();
        int[][] dp = new int[len1+1][len2+1];
         
        for(int i=0;i<=len1;i++){
            for(int j=0;j<=len2;j++){
                dp[i][j] = 0;//全部初始化为0
            }
        }
         
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                if(str1.charAt(i-1) == str2.charAt(j-1)){//表示str1前i个与str2前j个,此时字符串索引为i-1,j-1
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else{
                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);      
                }
            }
        }
        return dp[len1][len2];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值