最长公共子串及其长度

求2个串的最长公共子串及其长度

// 最长公共子串简称为lcs
// a[0]~a[i-1]的子串记为ai,a[0]~a[i-2]的子串记为a(i-1)
// b[0]~b[j-1]的子串记为bj,b[0]~b[j-2]的子串记为b(j-1)

#include
< iostream >
#include
< string >
#include
< vector >
using   namespace  std;

string  a; // 串a
int  m; // 串a长度
string  b; // 串b
int  n; // 串b长度
// c[i][j]记录ai与bj的lcs的长度
vector  <  vector  < int >   >  c; // lcs的长度记录在c[m][n]中

void  lenOfLcs() // DP
{
    
for ( int  i = 1 ;i <= m;i ++ )
    {
        
for ( int  j = 1 ;j <= n;j ++ )
        {
            
if  (a[i - 1 ] == b[j - 1 ])
                c[i][j]
= c[i - 1 ][j - 1 ] + 1 ; // 当前字符相等,lcs长度+1
             else   if  (c[i - 1 ][j] >= c[i][j - 1 ]) // 当前字符不相等,lcs长度为max(c[i-1][j],c[i][j-1])
                c[i][j] = c[i - 1 ][j];
            
else
                c[i][j]
= c[i][j - 1 ];
        }
    }
}     
    
string  lcs()     
{
    
int  i = m,j = n,k = c[m][n];
    
string  s = "" ;
    
    
while (k > 0 )
    {
        
if  (c[i][j] == c[i - 1 ][j]) // ai与bj的lcs与a(i-1)与bj的lcs相同
            i -- ;
        
else   if  (c[i][j] == c[i][j - 1 ]) // ai与bj的lcs与ai与b(j-1)的lcs相同
            j -- ;
        
else
        {
            s
= a[i - 1 ] + s; // +是连接符
            k -- ;
            i
-- ;
            j
-- ;
        }
    }
    
return  s;   
}   
    
bool  run()
{
    
if  ( ! (cin >> a >> b))  return   false ;
    m
= a.size();
    n
= b.size();
 
    c.resize(m
+ 1 );
    
for ( int  i = 0 ;i <= m;i ++ )
    {
        c[i].resize(n
+ 1 );
        c[i][
0 ] = 0 ; // b串为空时,lcs的长度为0
    }
    
    
for ( int  j = 0 ;j <= n;j ++ )  
    c[
0 ][j] = 0 ; // a串为空时,lcs的长度为0

    lenOfLcs();
    cout 
<<   " 最长公共子串的长度为: "   <<  c[m][n]  <<  endl; 
    cout 
<<   " 最长公共子串为: "   <<  lcs()  <<  endl;   

    
return   true ;
}

int   main()
{
    
while (run());     
    
return   0 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是C语言实现的LCS算法示例代码,供参考: ```c #include <stdio.h> #include <string.h> #include <math.h> #define MAXLEN 1000 int dist[MAXLEN][MAXLEN]; int path[MAXLEN][MAXLEN]; void lcs2(char* seq1, char* seq2) { int len1 = strlen(seq1); int len2 = strlen(seq2); // 初始化dist和path数组 for (int i = 0; i <= len1; i++) { dist[i][0] = 0; path[i][0] = 0; } for (int j = 0; j <= len2; j++) { dist[0][j] = 0; path[0][j] = 0; } // 动态规划计算dist和path数组 for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (seq1[i-1] == seq2[j-1]) { dist[i][j] = dist[i-1][j-1] + 1; path[i][j] = 1; } else if (dist[i-1][j] >= dist[i][j-1]) { dist[i][j] = dist[i-1][j]; path[i][j] = 2; } else { dist[i][j] = dist[i][j-1]; path[i][j] = 3; } } } // 从path数组中回溯出LCS int i = len1, j = len2, k = dist[len1][len2]; char lcs[MAXLEN]; while (k > 0) { if (path[i][j] == 1) { lcs[--k] = seq1[i-1]; i--; j--; } else if (path[i][j] == 2) { i--; } else { j--; } } // 输出结果 printf("Seq1: %s (%d)\n", seq1, len1); printf("Seq2: %s (%d)\n", seq2, len2); printf("LCS: "); for (int i = 0; i < dist[len1][len2]; i++) { printf("%c", lcs[i]); } printf(" (%d)\n", dist[len1][len2]); printf("SimS: %.2f\n", dist[len1][len2]/sqrt(len1*len2)); } int main() { char seq1[] = "ABCBDAB"; char seq2[] = "BDCABA"; lcs2(seq1, seq2); char seq3[] = "ACCGGTCGAGTGCGCGGAAGCCGGCCGGAA"; char seq4[] = "GTCGTTCGGAATGCCGTTGCTCTGTAAA"; lcs2(seq3, seq4); return 0; } ``` 输出结果为: ``` Seq1: ABCBDAB (7) Seq2: BDCABA (6) LCS: BCBA (4) SimS: 0.62 Seq1: ACCGGTCGAGTGCGCGGAAGCCGGCCGGAA (30) Seq2: GTCGTTCGGAATGCCGTTGCTCTGTAAA (28) LCS: GTCGTCGGAAGCCGGCCGAA (20) SimS: 0.69 ``` 其中,dist数组存储了最公共序列的长度,path数组存储了回溯路径,用于回溯出最公共序列。最后根据公式计算出相似度SimS。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值