最长公共字串

 

LCS问题就是求两个字符串最长公共子串的问题。解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为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 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 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 4 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,而是赋上其左上角元素的值加一。我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。

代码如下:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;

int main()
 {
   string str1,str2;
   str1="adbccadebbca";
   str2="adccbacaacece";
   int i,j,len1,len2;
   int c[100];
   int max=0,maxj=0;  //max和maxj是标记量
   memset(c,0,sizeof(c));
   len1=str1.length();
   len2=str2.length();

   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)  //把>改成>=则返回最后一个最长匹配子串
     {
      max=c[j]; //更新标志变量
      maxj=j;       
     }
    
    }
   
   
    cout<<str1.substr(maxj - max + 1,max)<<endl;     
    cin.get();      
    return 0;
}

### 关于最长公共子串 (LCS) 的解释 最长公共子串是指给定两个字符串序列,从中找出完全匹配的最长连续字符片段。不同于最长公共子序列(LCS),这里的子串要求是连续的[^2]。 ### C# 中实现最长公共子串算法 为了实现在C#中的最长公共子串算法,可以采用动态规划的方法。这种方法通过构建一个二维数组`dp`来存储中间计算的结果,其中`dp[i][j]`表示第一个字符串前i个字符和第二个字符串前j个字符之间的最大公共子串长度。当遇到相同字符时更新该位置的最大值并记录结束位置;如果不同则重置当前比较长度为0。 下面是具体的C#代码实现: ```csharp using System; class Program { static void Main() { string str1 = "acbcbcef"; string str2 = "abcbced"; Tuple<string, int> result = FindLongestCommonSubstring(str1, str2); Console.WriteLine($"The longest common substring is '{result.Item1}' with length {result.Item2}"); } public static Tuple<string, int> FindLongestCommonSubstring(string s1, string s2){ int[,] dp = new int[s1.Length + 1, s2.Length + 1]; int maxLength = 0; int endIndexS1 = 0; for(int i = 1; i <= s1.Length; ++i){ for(int j = 1; j <= s2.Length; ++j){ if(s1[i - 1] == s2[j - 1]){ dp[i,j] = dp[i-1,j-1] + 1; if(dp[i,j] > maxLength){ maxLength = dp[i,j]; endIndexS1 = i; } }else{ dp[i,j] = 0; } } } return Tuple.Create(s1.Substring(endIndexS1 - maxLength, maxLength), maxLength); } } ``` 上述程序定义了一个名为 `FindLongestCommonSubstring` 的函数,它接收两个参数作为输入,并返回由元组组成的输出,其中包括最长公共子串及其对应的长度。此方法利用了动态规划的思想,在遍历过程中不断寻找最优解直到整个表格被填满为止[^1]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值