两个字符串的最长连续公共子串

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

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

比如:

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 1 0 0 0 0 0 0 0 1 1 0 0 0 
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 
  0 1 0 0 0 0 0 0 0 1 1 0 0 0 
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 
  0 0 0 1 0 0 0 1 1 0 0 1 0 0 
  1 0 1 0 1 0 1 0 0 0 0 0 1 0 
  1 0 1 0 1 0 1 0 0 0 0 0 1 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 1 
  0 0 0 0 0 0 0 0 0 0 0 0 0 1 
  0 0 0 0 0 1 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 1 0 0 0 0 0 0 0 2 1 0 0 0 
  1 0 2 0 1 0 1 0 0 0 0 0 1 0 
  0 2 0 0 0 0 0 0 0 1 1 0 0 0 
  1 0 3 0 1 0 1 0 0 0 0 0 1 0 
  0 0 0 4 0 0 0 2 1 0 0 1 0 0 
  1 0 1 0 5 0 1 0 0 0 0 0 2 0 
  1 0 1 0 1 0 1 0 0 0 0 0 1 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 1 
  0 0 0 0 0 0 0 0 0 0 0 0 0 1 
  0 0 0 0 0 1 0 0 0 0 0 0 0 0 
当字符匹配的时候,我们并不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。

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

void getLCS(char* str1, char* str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    int *matrix = new int[len1]; //str1为x方向
    //初始化matrix
    for (int i = 0; i < len1; i++)
    {
        matrix[i] = 0;
    }
    int *maxValue = new int[len2];//str2为y方向,最多有len2个最大值
    int *maxIndex = new int[len2];
    //初始化maxValue和maxIndex
    for (int i = 0; i < len2; i++)
    {
        maxValue[i] = -1;
        maxIndex[i] = -1;
    }
    for (int i = 0; i < len2; i++)
    {
        for (int j = len1 - 1; j >= 0; j--)
        {
            //扫描str1与str2的各个字符的匹配情况
            if (str2[i] == str1[j])
            {
                if (j == 0)
                {
                    matrix[j] = 1;
                }
                else
                {
                    matrix[j] = matrix[j - 1] + 1;
                }
            }
            else
            {
                matrix[j] = 0;
            }
            if (matrix[j] != 0 && matrix[j] > maxValue[0])
            {
                //更新maxValue的值
                maxValue[0] = matrix[j];
                maxIndex[0] = j;
                //将其他的maxValue重置
                for (int i = 1; i < len2; i++)
                {
                    maxValue[i] = -1;
                    maxIndex[i] = -1;
                }
            }
            else if (matrix[j] == maxValue[0])//有多个最大连续公共子串
            {
                for (int i = 1; i < len2; i++)
                {
                    if (maxValue[i] == -1)
                    {
                        maxValue[i] = matrix[j];
                        maxIndex[i] = j;
                        break; //只需加一个
                    }
                }
            }
        }
    }
    for (int i = 0; i<len2; i++)
    {
        if (maxValue[i]>0)
        {
            cout << "第" << i + 1 << "个公共子串" << endl;
            for (int j = maxIndex[i] - maxValue[i] + 1; j <= maxIndex[i]; j++)
            {
                cout << str1[j];
            }
            cout << endl;
        }
    }
}
时间: 2024-10-12 10:58:57

两个字符串的最长连续公共子串的相关文章

寻找两个字符串中最长的公共子串源码(不使用strcmp)

#include <stdio.h> #include <string.h> #include <stdlib.h> char *com_child(const char *str1, const char *str2); int main(void) { char str1[] = "abcdefgehi", str2[] = "aacdef**gehicdefgeabcdefgehi", *strtemp = NULL; st

最长连续公共子串、最长公共子串(可以非连续)、最长回文串(连续)、最长回文串(可以不连续)、最长递增数组的求解

问题:最长连续公共子串.最长公共子串(可以非连续).最长回文串(连续).最长回文串(可以不连续).最长递增数组.长方形镶嵌最多的求解 方法:上述问题有相似性,都可以采用动态规划进行求解. (1)最长连续公共子串: 如果A[i]==B[j], dp[i][j]=dp[i-1][j-1]+1; 否则,dp[i][j]=0; (2)最长公共子串(可非连续): 如果A[i]==B[j], dp[i][j]=dp[i-1][j-1]+1; 否则,dp[i][j]=dp[i-1][j-1]; (3)最长回文

后缀数组的使用心得——POJ2774 最长连续公共子串

对于这道题,将两个字符串直接合并成为一个字符串,分别记录连个字符串结束的位置. 首先,应用黑暗圣典的模板,我们可以顺利得到height,rank,sa三个数组. 之后直接扫描1-n所有的位置,选出来一个,符合"两者都在不同子串的最大长度即可". 此时我们会发现,sa数组记录了每个子串开头的位置,可以用于判断. #include<iostream> #include<stdio.h> #include<string> #include<strin

求两个字符串的最长公共子串——Java实现

要求:求两个字符串的最长公共子串,如"abcdefg"和"adefgwgeweg"的最长公共子串为"defg"(子串必须是连续的) public class Main03{ // 求解两个字符号的最长公共子串 public static String maxSubstring(String strOne, String strTwo){ // 参数检查 if(strOne==null || strTwo == null){ return null

求解两个字符串的最长公共子序列

一,问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符串1:BDCABA:字符串2:ABCBDAB 则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA 二,算法求解 这是一个动态规划的题目.对于可用动态规划求解的问题,一般有两个特征:①最优子结构:②重叠子问题 ①最优子结构 设 X=(x1,x2,.....xn) 和 Y={y1,y2,.....ym} 是两个序列,将 X 和 Y 的最长公共子序列记为LCS(X,

面试宝典_Python.常规算法.0002.输出任意两个字符串中最长公共子串?

面试题目: 1. 用PY实现求任意两个字符串最长的公共子串? 解题思路: 1. 先求出长度最小的字符串,然后遍历其索引,这样可以避免字符串索引溢出,然后判断对应索引的值是否相同,相同的话就加到目标字典,不同的话就更新目标字典索引,但不存储,最后再按照值长度逆向排序取出第一个元素即可. 具体实现: #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: http://x

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

import java.util.Scanner; /* 求两个字符串的最长公共子串*/ public class stringDemo {     public static void main(String[] args){      Scanner scanner = new Scanner(System.in);      System.out.println("请输入第一个字符串:");      String str1 = scanner.nextLine();     

Java算法——求出两个字符串的最长公共字符串

问题:有两个字符串str1和str2,求出两个字符串中最长公共字符串. 例如:“acbbsdef”和"abbsced"的最长公共字符串是“bbs” 算法思路: 1.把两个字符串分别以行和列组成一个二维矩阵. 2.比较二维矩阵中行和列对应的每个点的字符是否相同,是设置这个点为1,否设置这个点为0. 3.通过查找值为1的最长对角线来找到最长公共字符串. 通过上面str1和str2两个字符串,分别得出以行和列组成的一个二维矩阵如下图: 从上图可以看到,str1和str2共有3个公共子串&qu

动态规划之----求两个字符串的最长公共子序列

package DongtaiGuihua; /** * Created by hunk on 2015/9/13. */public class LongestCommonSubstring { public static void main(String[] args){ String str1="BDCABA"; String str2="ABCBDAB"; System.out.println(findMaxCommonSubstring(str1,str2