赞
踩
题目描述
查找两个字符串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]; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。