`
longgangbai
  • 浏览: 7330349 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】求两个字符串最长公共子串的问题

阅读更多

LCS(Longest Common Subsequence) 就是求两个字符串最长公共子串的问题。

link:http://blog.csdn.net/zztfj/article/details/6157429

比如:

 

  String str1 = new String("adbccadebbca");
  String str2 = new String("edabccadece");
str1与str2的公共子串就是bccade.

    解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置.

    下面是字符串21232523311324和字符串312123223445的匹配矩阵,前者为X方向的,后者为Y方向的。不难找到,红色部分是最长的匹配子串。通过查找位置我们得到最长的匹配子串为:21232


  0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
  0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
  0 0 0 0 0 0 0 0 1 1 0 0 0 0
  1 0 0 1 0 1 0 0 0 0 0 1 0 0
  0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
  0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
  0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 
  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
但是在0和1的矩阵中找最长的1对角线序列又要花去一定的时间。通过改进矩阵的生成方式和设置标记变量,可以省去这部分时间。下面是新的矩阵生成方式: 
  0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
  0 1 0 0 0 0 0 0 0 2 1 0 0 0 0
  1 0 2 0 1 0 1 0 0 0 0 0 1 0 0
  0 2 0 0 0 0 0 0 0 1 1 0 0 0 0
  1 0 3 0 1 0 1 0 0 0 0 0 1 0 0
  0 0 0 0 0 0 2 1 0 0 1 0 0 0
  1 0 1 0 5 0 1 0 0 0 0 0 2 0 0
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
  0 0 0 2 0 0 0 2 1 0 0 1 0 0 0
  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
  0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
当字符匹配的时候,我们并不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。具体算法如下:

 

  1. void lcs(char a[],char b[],int len1,int len2)  
  2. {  
  3.     assert(len1>0 && len2 > 0);  
  4.     int max=0;//标记公共子串的最大长度  
  5.     int row=0,col=0;//标记公共子串的行列  
  6.     int **c= new int*[len2+1];  
  7.     for(int i=0;i<len2+1;++i)  
  8.         c[i]=new int[len1+1];  
  9.   
  10.     for(int i=0;i<len2+1;++i) //赋初值  
  11.         for(int j=0;j<len1+1;++j)  
  12.             c[i][j]=0;  
  13.   
  14.     for(int i=1;i<len2+1;++i)  
  15.         for(int j=1;j<len1+1;++j)  
  16.             if(b[i-1]==a[j-1])  
  17.             {  
  18.                 c[i][j]=c[i-1][j-1]+1;  
  19.                 if(c[i][j]>max)  
  20.                 {  
  21.                     max=c[i][j];  
  22.                     row=i;  
  23.                     col=j;  
  24.                 }  
  25.             }  
  26.     for(int k=row-max;k<=row-1;k++)  
  27.         cout<<b[k];  
  28. }  



 

  这样做速度比较快,但是花的空间太多。我们注意到在改进的矩阵生成方式当中,每生成一行,前面的那一行就已经没有用了。因此我们只需使用一维数组即可。最终的代码如下:

public class LCString2 {

    
public static void getLCString(char[] str1, char[] str2)
    
{
        
int i,j;
        
int len1,len2;
        len1 
= str1.length;
        len2 
= str2.length;
        
int maxLen = len1 > len2?len1:len2;
        
int[] max = new int[maxLen];
        
int[] maxIndex = new int[maxLen];
        
int[] c = new int[maxLen];
        
        
for (i = 0; i < len2 ; i++)
        
{
            
for (j = len1 -1; j >= 0; j--)
            
{
                
if (str2[i] == str1[j]) 
                
{
                    
if ( ( i == 0|| (j == 0) )
                        c[j] 
= 1;
                    
else
                        c[j] 
= c[j-1+ 1;
                }

                
else
                
{
                    c[j] 
= 0;
                }

                
                
if (c[j] > max[0])
                
{   //如果是大于那暂时只有一个是最长的,而且要把后面的清0;
                    max[0= c[j];
                    maxIndex[
0= j;
                    
                    
for (int k = 1; k < maxLen; k++)
                    
{
                        max[k] 
= 0;
                        maxIndex[k] 
= 0;
                    }

                }

                
else if (c[j] == max[0])
                
{   //有多个是相同长度的子串
                    for (int k = 1; k < maxLen; k++)
                    
{
                        
if (max[k] == 0)
                        
{
                            max[k] 
= c[j];
                            maxIndex[k] 
= j;
                            
break;  //在后面加一个就要退出循环了
                        }

                
                    }

                }

            }

        }

        
        
for (j = 0; j < maxLen; j++)
        
{
            
if (max[j] > 0)
            
{
                System.out.println(
"" + (j + 1+ "个公共子串:");
                
for (i = maxIndex[j] - max[j] + 1; i <= maxIndex[j]; i++)
                    System.out.print(str1[i]);
                System.out.println(
" ");
            }
            
        }

    }


    
public static void main(String[] args) {
        
        String str1 
= new String("adbba1234");
        String str2 
= new String("adbbf1234sa");
        getLCString(str1.toCharArray(),str2.toCharArray());
    }

}

分享到:
评论

相关推荐

    JavaScript自定义函数实现查找两个字符串最长公共子串的方法

    本文实例讲述了JavaScript自定义函数实现查找两个字符串最长公共子串的方法。分享给大家供大家参考,具体如下: //查找两个字符串的最长公共子串 function findSubStr(s1,s2){ var S=sstr= ,L1=s1.length,L2=s2....

    C语言求两个字符串的最长公共子串

    本文实例讲述了C语言求两个字符串的最长公共子串的方法。分享给大家供大家参考。具体实现方法如下: #include "stdio.h" #include "string.h" #include "stdlib.h" void getCommon(char str1[],char str2[],char * ...

    java实现求两个字符串最长公共子串的方法

    在编程领域,求解两个字符串的最长公共子串是一个经典问题,主要应用于文本处理、比较和搜索算法。这里我们将深入探讨如何使用Java实现这一方法,同时结合华为在线判题平台(OJ)的要求来编写代码。 首先,我们需要...

    PHP实现求两个字符串最长公共子串的方法示例

    在这个问题中,我们专注于PHP如何解决两个字符串的最长公共子串。 PHP作为一门广泛使用的服务器端脚本语言,提供了丰富的字符串和数组操作函数,这使得处理LCS问题变得相对容易。在给定的代码示例中,我们看到一种...

    用定长顺序存储结构表示串,求两个串的全部最长公共子串

    在本题目中,任务是使用定长顺序存储结构表示串,并找出两个字符串的最长公共子串。这是一个典型的字符串处理问题,通常在计算机科学和编程领域出现。以下是对这个任务的详细解析: 首先,我们需要理解“定长顺序...

    python实现求两个字符串的最长公共子串方法

    在Python编程语言中,求解两个字符串的最长公共子串是一项常见的字符串处理任务。这个问题的解决方案通常基于动态规划思想,即将问题分解为更小的子问题,并存储子问题的解以便于后续使用,从而避免重复计算。下面...

    在随意给出的2个字符串中,找出它们共同的最长的子串

    在随意给出的2个字符串中,找出它们共同的最长的子串。 【输入】 输入文件的第一行为一个整数2,接下来有2行,每行为一个字符串,每个字符串的长度均小于255。 【输出】 输出只有一行,即:共同的最长子串,若有多个...

    求两个字符串的最长公共字串

    通过上述分析,我们可以看到,这段程序实现了对两个字符串的最长公共子串的有效计算。尽管其实现方式相对简单,但对于理解和学习动态规划的基本思想具有很好的参考价值。此外,在实际应用中,还可以考虑使用更高效的...

    查找最长公共子串

    现在,我们要寻找两个字符串a和b中最长的公共子串。这个问题可以通过动态规划来解决。动态规划是一种利用已解决问题的解来构建更复杂问题的解的方法,它能有效地避免重复计算,提高效率。 动态规划解决方案通常涉及...

    C++实现找出两个字符串中最大的公共子串

    本主题将深入探讨如何使用C++语言来实现一个算法,该算法能够找出两个字符串中的最大公共子串。公共子串是指同时存在于两个或多个字符串中的任意非空字符序列。在本问题中,我们目标是找到最长的这样一个子串。 ...

    找两字符串中最大子串

    - **目标**:找出这两个字符串的最长公共子串。 #### 2. 算法步骤 该算法的核心思想是通过双重循环遍历两个字符串,逐个字符进行比较,以找到最长的匹配子串。 - **初始化**:首先设置两个指针`flag1`和`flag2`,...

    最长公共子串MFC实现

    接下来,我们遍历两个字符串,如果当前字符相同,则dp[i][j] = dp[i-1][j-1] + 1,否则dp[i][j]取dp[i-1][j]和dp[i][j-1]中的较大值。最后,最长公共子串的长度就是dp数组的最大值,而子串本身可以通过回溯dp数组...

    java实现字符串匹配求两个字符串的最大公共子串

    在Java编程中,实现字符串匹配并...总之,Java实现字符串匹配求两个字符串的最大公共子串是一个涉及字符串处理和动态规划的经典问题。通过理解上述算法思想和代码实现,开发者可以有效地处理文本数据的比较和分析任务。

    求两个字符串的最长公共字串。

    求两个字符串的最长公共子串是一个典型的字符串处理问题,在实际应用中有着广泛的需求。通过对暴力法和动态规划法的理解与实践,可以更好地掌握字符串处理的相关技术。希望本文能够帮助读者深入理解这一问题,并在...

    求最长的公共子串

    两个字符串里求最长的公共子串

    新建 WinRAR 压缩文件_最长公共子串_

    在给定的压缩包文件中,我们可以看到它包含了用于开发和编译C++程序的相关文件,这表明我们将讨论如何用C++实现寻找两个字符串的最长公共子串的算法。 "最长公共子串"是指在两个或多个字符串中,长度最长的那个相同...

Global site tag (gtag.js) - Google Analytics