首页 > 试题广场 >

给两个字符串,输出其最长共同字符串的长度:如 S1: asd

[问答题]
给两个字符串,输出其最长共同字符串的长度:如
S1: asdfghjqweryuiase
S2: astyfrtfghjqwsa
其最长共同字符串为fghjqw 长度为6,给出代码。
本题目主要考察动态规划、最长公共子序列问题:
/***
* 计算最最长公共子序列问题 解题思路: 要求找到X={x1、x2、x3...xm}和 Y
* ={y1、y2、y3...yn}的最长公共子序列可用递归思想做如下考虑
* 1.当xm=yn时,找到X(m-1)和Y(n-1)的最长公共子序列,然后再其尾部添加上xm=yn即可得X和Y的最长公共子序列;
* 2.当xm!=yn时
* ,需要找到,X(m-1)和Y的一个最长公共子序列及X和Y(n-1)的一个最长公共子序列,这两个公共子序列的较***即为X和Y的最长公共子序列;
* @param args
*/
源代码如下:
public static char[] lcs(char[] a, char[] b) {
int len_a = a.length;
int len_b = b.length;
char[] p;
int[][] c = new int[N][N];
int start, end, len, i, j;
end = len = 0;
for (i = 0; i < len_a; i++) {
for (j = 0; j < len_b; j++) {
if (a[i] == b[j])
if (i == 0 || j == 0)
c[i][j] = 1;
else
c[i][j] = c[i - 1][j - 1] + 1;
if (c[i][j] > len) {
len = c[i][j];
end = j;
}
}
}
start = end - len + 1;
p = new char[len + 1];
for (i = start; i <= end; i++)
p[i - start] = b[i];
p[len] = '\0';
/*for (j = 0; j < len_b; j++) {
for (i = 0; i < len_a; i++)
System.out.print(c[i][j]+"\t");
}*/
return p;
}
返回的数组就是最长公共子序列,序列的长度为p.length;
发表于 2016-01-22 14:21:02 回复(1)
更多回答
    public static void main(String[] args) {
        String s1 = "asdfghjqweryuiase";
        String s2 = "astyfrtfghjqwsa";
        System.out.print(findMaxSame(s1, s2));
    }
    private static String findMaxSame(String s1, String s2) {
        int l1 = s1.length();
        String maxSame = "";
        String subString = "";
        for (int i = 0; i < l1; i++) {
            for (int j = i + 1; j < l1; j++) {
                subString = s1.substring(i, j);
                if (s2.indexOf(subString) >= 0) {
                    maxSame = subString.length() > maxSame.length() ? subString : maxSame;
                } else {
                    break;
                }
            }
        }
        return maxSame;
    }

发表于 2015-05-21 17:41:23 回复(2)
#include <iostream> using namespace std; int dp[30][30]; int maxLen = 0; int maxIndex = 0; void output(char * s) { for(int l = 0; l < maxLen; l++) { printf("%c",s[l+maxIndex]); } printf("\n"); } void LCString_DP(char* X,int XLen,char* Y,int YLen) { if( X == NULL || Y == NULL || XLen <= 0 || YLen <= 0) return; for(int i = 0; i < XLen; i++) { for(int j = 0; j < YLen; j++ ) { if(X[i]==Y[j]) { if(i==0 || j == 0) dp[i][j] = 1; if(i && j){ dp[i][j] = dp[i-1][j-1] + 1; } if(maxLen < dp[i][j]) { maxLen = dp[i][j]; maxIndex = i - maxLen + 1; //i,j的意思是说,当dp[i][j]为最长公共子串的长度时, // i,j各自代表本串满足条件最远位置,所以才会有 i-maxLen+1 } } } } printf("%d\n",maxIndex); printf("%d\n",maxLen); output(X); } int main(void) { char* A = "aaaaaa"; char* B = "ab"; // cout << strlen(A)<<endl; // cout << strlen(B)<<endl; LCString_DP(A, strlen(A)+1, B, strlen(B)+1); return 0; }
发表于 2014-10-12 20:27:45 回复(16)
package 最长公共子串;

public class Main {
    private static int length = 0;

    public static void main(String[] args) {
        Main main = new Main();
        String s1 = "asdfghjqweryuiase";
        String s2 = "astyfrtfghjqwsa";
        String maxStr = main.searchForCommonStr(s1, s2);
        System.out.println("最长公共子串为" + maxStr);
        System.out.println("长度为:" + length);
    }

    /**
     * maxStr用于记录最大公共子字符串
     * maxLength用于记录最大公共子字符串的长度
     * 从下标为0开始,依次截取起始下标为0的s1的子字符串substring
     * 依次与s2匹配有无公共字符串substring
     * 若有,且substring的长度大于maxLength,则maxLength = substring.length(); maxStr = substring;
     * 否则,继续循环
     */
    public String searchForCommonStr(String s1, String s2) {
        String maxStr = "";
        int maxLength = 0;

        for (int start = 0; start < s1.length(); start++) {
            for (int end = start + 1; end < s1.length(); end++) {

                String substring = s1.substring(start, end);
                if (s2.indexOf(substring) != -1) {
                    if (substring.length() > maxLength) {
                        maxLength = substring.length();
                        maxStr = substring;
                        length = maxLength;
                    }
                }

            }
        }
        return maxStr;
    }
}

发表于 2021-03-13 15:26:57 回复(0)

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author zhangtao
 */
public class ComlongStr {

    public static void main(String[] args) throws IOException {

        String str1 = "";
        String str2 = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        str1 = br.readLine();
        str2 = br.readLine();
        showComLongStr(str1, str2);
    }

    private static void showComLongStr(String str1, String str2) {
        String minStr = str1.length() < str2.length() ? str1 : str2;
        String maxStr=str1.length() > str2.length() ? str1 : str2;
        int minStrLong=minStr.length();
        String comStr="";
        outer:
        for(int i=0;i<minStrLong;i++)
        {
            for(int j=0;j<i+1;j++)
            {
                String tempStr=minStr.substring(j,minStrLong-i+j);
                //System.out.println("tempStr  "+tempStr);
                if(maxStr.contains(tempStr))
                {
                    comStr=tempStr;
                    break outer;
                }
                else
                {
                    continue;
                }
            }
        }
        //System.out.println("minStr  "+minStr);
        //System.out.println("maxStr  "+maxStr);

        System.out.println(comStr);
    }

}

发表于 2017-09-14 15:33:24 回复(0)
1.首先以较短的那个字符串为准开始匹配,因为就算全部字符串都能匹配到,那也只可能是最短字符串全部。如果以较多字符串来匹配的话,那么匹配到后,可能还会在后面全匹配到,当然你也可以添加判断条件,一旦匹配到就退出。
2.我们应该以从长到短开始匹配。因为假如有两个字符串,假设最短那个长度是6,当你匹配到两个字符串长度为2相同的时候,可能后面还会匹配到长度为3相同的字符串。反过来,假如你匹配到长度为3相等的时候,你就不必要匹配长度为2相等的了,也就是你一旦找到最大长度的时候,你就不必要最匹配短的了。
3.为避免匹配不到相同字符串出现空指向异常,所以String初始化时赋值空字符串,及 String string = new String("")。
JAVA代码如下:
public static void main(String[] args)  {
        String s2= "GCCCTAGCCAGDE";
        String s1= "GCGCCAGTGDE";
        System.out.println(getMaxLength(s1,s2).length());
    }
    public static String getMaxLength(String str1, String str2) {
        boolean flag = false;
        String s1 = str1;
        String s2 = str2;
        String string = new String("");
        if (s1.length() > s2.length()) {
            string = s1;
            s1 = s2;
            s2 = string;
        }
        for (int i = s1.length(); i > 0; i--) {
            for (int n = 0; n<= s1.length() - i; n++) {
                if (s2.contains(s1.substring(n, n + i))) {
                    string = s1.substring(n, n + i);
                    flag = true;
                    break;
                }
            }
            if (flag)
                break;
        }
        return string;
}

发表于 2017-03-21 13:41:34 回复(0)
# mat[-1][-1] 即所求长度
def subString(string, substr):
l1 = len(string)
l2 = len(substr)
mat = [[0 for i in range(l1 + 1)] for i in range(l2 + 1)]
for i in range(1, l2+1):
for j in range(1, l1+1):
if string[j-1] == substr[i-1]:
mat[i][j] = mat[i-1][j-1] + 1
else:
if mat[i-1][j] > mat[i][j-1]:
mat[i][j] = mat[i-1][j]
else:
mat[i][j] = mat[i][j-1]
	return mat

发表于 2016-10-18 15:47:09 回复(0)
最长公共子序列可以转化成最长上升子序列的问题,然后用最长上升子序列的 nlogn 的算法求解。
时间复杂度可以从O(n^2)下降到O(nlogn),但并不是严格上的
动态规划:dp[i][j]表示A串前i个和B串前j个的最长公共子串的长度。

若A[i] == B[j] , dp[i][j] = dp[i-1][j-1] + 1;
否则 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
时间复杂度O(N*M)。
dp[i][j]仅在A[i]==B[j]处才增加,对于不相等的地方对最终值是没有影响的。
故枚举相等点处可以对其进行优化。
则对于dp[i][j](这里只计算A[i]==B[j]的i和j),取最大的dp[p][q],满足(p<i,q<j),通过二叉搜索树可以再logn的时间里获取到最大的dp[p][q],区间在[0,j)。
这里也可将其转化为最长递增子序列问题。
举例说明:
A:abdba
B:dbaaba
则1:先顺序扫描A串,取其在B串的所有位置:
    2:a(2,3,5) b(1,4) d(0)。
    3:用每个字母的反序列替换,则最终的最长严格递增子序列的长度即为解。
替换结果:532 41 0 41 532
最大长度为3.
简单说明:上面的序列和最长公共子串是等价的。
对于一个满足最长严格递增子序列的序列,该序列必对应一个匹配的子串。
反序是为了在递增子串中,每个字母对应的序列最多只有一个被选出。
反证法可知不存在更大的公共子串,因为如果存在,则求得的最长递增子序列不是最长的,矛盾。
最长递增子序列可在O(NLogN)的时间内算出。
dp[i] = max(dp[j]+1) ( 满足 a[i] > a[j] && i > j )
显然对于同样的如dp[k] = 3,假定k有多个,记为看k1,k2,.....,km 设k1 < k2 < .... < km
在计算dp[i]的时候,k2,k3,....,km显然对结果没有帮助,取当前最小的k,
满足ans[k] = p (最小的p使得dp[p]=k) ,每次二分,更新ans[dp[i] = min(ans[dp[i],i).
 
ps:LCS在最终的时间复杂度上不是严格的O(nlogn),
const int maxn = 1501 ;  
vector<int> location[26] ;  
int c[maxn*maxn] , d[maxn*maxn] ;  
 
inline int get_max(int a,int b) {   return a > b ? a : b ;  }  
 
//nlogn 求lcs  
int lcs(char a[],char b[])  
{  
    int i , j , k , w , ans , l , r , mid ;  
    for( i = 0 ; i < 26 ; i++) location[i].clear() ;  
    for( i = strlen(b)-1 ; i >= 0 ; i--) location[b[i]-'a'].push_back(i) ;  
    for( i = k = 0 ; a[i] ; i++)  
    {  
        for( j = 0 ; j < location[w=a[i]-'a'].size() ; j++,k++) c[k] = location[w][j] ;  
    }  
    d[1] = c[0] ;   d[0] = -1 ;  
    for( i = ans = 1 ; i < k ; i++)  
    {  
        l = 0 ; r = ans ;  
        while( l <= r )  
        {  
            mid = ( l + r ) >> 1 ;  
            if( d[mid] >= c[i] ) r = mid - 1 ;  
            else l = mid + 1 ;  
        }  
        if( r == ans ) ans++,d[r+1] = c[i] ;  
        else if( d[r+1] > c[i] ) d[r+1] = c[i] ;  
    }  
    return ans ;  
}  
 
int main()  
{  
    char a[maxn] , b[maxn] ;  
    while (~scanf("%s%s",a,b))  
    {  
        printf("%d/n",lcs(a,b));  
    }  
} 
编辑于 2016-01-22 14:08:03 回复(0)
<pre class="prettyprint lang-java">public static int&nbsp; getMaxStringLength(Set&lt;String&gt; s1,Set&lt;String&gt; s2){ &nbsp;&nbsp;String s=""; &nbsp;&nbsp;Set&lt;String&gt; set=new HashSet&lt;String&gt;(); &nbsp;&nbsp;Iterator&lt;String&gt; iterA=s1.iterator(); &nbsp;&nbsp;Iterator&lt;String&gt; iterB=s2.iterator(); &nbsp;&nbsp;while(iterA.hasNext()&amp;&amp;iterB.hasNext()){ &nbsp;&nbsp;&nbsp;s=iterB.next(); &nbsp;&nbsp;&nbsp;if(s1.contains(s)){ &nbsp;&nbsp;&nbsp;&nbsp;//System.out.println(s+" "); &nbsp;&nbsp;&nbsp;&nbsp;set.add(s); &nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;} &nbsp;&nbsp;return set.size(); &nbsp;}</pre> <br />
发表于 2015-09-19 18:55:24 回复(0)
<div> #include &lt;iostream&gt; </div> <div> using namespace std; </div> <div> int main(){ </div> <div> &nbsp; &nbsp; string s1, s2; </div> <div> &nbsp; &nbsp; cin&gt;&gt;s1&gt;&gt;s2;<br /> </div> <div> &nbsp; &nbsp; int dp[s1.size()][s2.size()];<br /> </div> <div> &nbsp; &nbsp; int i, j;<br /> </div> <div> &nbsp; &nbsp; for(i=0; i&lt;s1.size(); ++i)<br /> </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; if(s1[i]==s2[0])&nbsp; &nbsp; dp[i][0] = 1;<br /> </div> <div> &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; else dp[i][0] = 0;<br /> </div> <div> &nbsp; &nbsp; for(j=0; j&lt;s2.size(); ++j)<br /> </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; if(s2[j]==s1[0])&nbsp; &nbsp; dp[0][j] = 1;<br /> </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; else dp[0][j]=0;<br /> </div> <div> &nbsp; &nbsp; for(i=1; i&lt;s1.size(); ++i){ </div> <div> &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; for(j=1; i&lt;s2; ++j){ </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; if(s1[i]==s2[j])&nbsp; &nbsp; dp[i][j] = dp[i-1][j-1]+1;<br /> </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; else dp[i][j]=0;<br /> </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; }<br /> </div> <div> &nbsp;&nbsp;&nbsp;&nbsp;}<br /> </div> <div> &nbsp; &nbsp; cout&lt;&lt;dp[i-1][j-1]&lt;&lt;endl;<br /> </div> <div> &nbsp; &nbsp; return 0;<br /> </div> <div> } </div>
发表于 2015-09-11 19:55:34 回复(0)
<pre class="prettyprint lang-java">public int getComLength(String s1, String s2){ char[] text = s1.toCharArray(); char[] query = s2.toCharArray(); int textLen = text.length; int queryLen = query.length; int[] length = new int[textLen]; for(int i=0;i&lt;textLen-1;i++){ &nbsp; int size = 0; &nbsp; int tmp = i; for(int j=queryLen-1;j&gt;=0;){ if(text[i]==query[j]){ size++; i--; j--; if(i&lt;0){ break; } }else{ if(j==queryLen-1){ j--; }else{ break; } } } length[tmp] = size; i = tmp; } return getMax(length); } public int getMax(int[] a){ int len = a.length; int max = a[0]; for(int i=1;i&lt;len;i++){ if(a[i]&gt;max) max = a[i]; } return max; }</pre> <br />
发表于 2015-09-08 12:48:18 回复(0)
int dp(char *s1, char *s2) {
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    int d[l1 + 10][l2 + 10];
    memset(d, 0, sizeof(d));
    for (int i = 1; i <= len1; i++) {
        for (int j = 1; j <= len2; j++) {
            if (s1[i-1] == s2[j-1]) {
                d[i][j] = d[i-1][j-1]+1;
            }
            else d[i][j] = max(d[i-1][j], d[i][j-1]);
        }
    }
    return d[l1][l2];
}

发表于 2015-06-09 20:38:41 回复(1)
$S1 = 'asdfghjqweryuiase';
$S2 = 'astyfrtfghjqwsa';
$count1 =strlen($S1);
$count2 =strlen($S2);
$len = 0;
for ($i=0; $i <$count2 ; $i++) {
    for ($j=1; $j < $count2 - $i +1; $j++) { 
        $str = substr($S2, $i ,$j);
        if(strpos($S1,$str)){
            if (strlen($str)>=$len) {
                $len = strlen($str);
            }
            
        }
    }
}

php 代码,测试过的,可以得出结果,(上海 ,qq:641257395,wang)
发表于 2015-05-30 22:58:07 回复(0)
KMP
发表于 2014-10-11 15:58:19 回复(1)