最长公共子串及其长度

求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
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值