求2个字符串的最长公共子序列(Longest Common Subsequence)
运用动态规划,复杂度为O(mn)m,n分别为两子序列长度
设:
两个序列Xi 和Yj的lcs为c[i,j]
如果图片显示不清楚,可在:
http://super-jiju.spaces.live.com/blog/cns!806C498DDEE76B61!270.entry
查看
根据上面的递归式即可
但不需要用递归求解,因为c[i,j]已经保存了每一对值
然后,回溯求得
#include
<
iostream
>
#include
<
string
>
using
namespace
std;
int
lcs(
string
A,
string
B);
int
c[
100
][
100
]
=
...
{ 0 }
;
int
b[
100
][
100
]
=
...
{ 0 }
;
void
image(
int
i,
int
j,
string
&
A);
int
main()
...
{ string a,b; cin >> a >> b; if (a.length() > 100 || b.length() > 100 ) ... { cerr << " Can not get the lcs of the string which length over 100 " << endl; exit( 0 ); } string & aa = a; cout << " " << endl; lcs(a,b); cout << " " << endl; image(a.length(),b.length(),aa); cout << endl; system( " pause " ); return 0 ; }
int
lcs(
string
A,
string
B)
...
{ int mA = A.length(); int nB = B.length(); int len = 0 ; for ( int i = 1 ;i <= mA; ++ i) ... { for ( int j = 1 ;j <= nB; ++ j) ... { if (A.at(i - 1 ) == B.at(j - 1 )) ... { c[i][j] = c[i - 1 ][j - 1 ] + 1 ; len ++ ; b[i][j] = 3 ; } else if (c[i - 1 ][j] >= c[i][j - 1 ]) ... { c[i][j] = c[i - 1 ][j]; b[i][j] = 1 ; } else ... { c[i][j] = c[i][j - 1 ]; b[i][j] = 2 ; } } } // -----image the road for ( int j = 1 ;j <= nB; ++ j) ... { cout << " " << B.at(j - 1 ); } cout<< endl; for ( int i = 1 ;i <= mA; ++ i) ... { cout << A.at(i - 1 ) << " " ; for ( int j = 1 ;j <= nB; ++ j) ... { cout << b[i][j] << " " ; } cout<< " " << endl; } return len; }
void
image(
int
i,
int
j,
string
&
A)
...
{ // -----3:up and left,1:up,2:left if (i == 0 || j == 0 ) return ; if (b[i][j] == 3 ) ... { cout << A.at(i - 1 ) << " " ; image(i - 1 ,j - 1 ,A); } if (b[i][j] == 1 ) image(i - 1 ,j,A); if (b[i][j] == 2 ) image(i,j - 1 ,A); }
比如输入结果:
ABCBDAB
BDCABA
得到:
B D C A B A
A 1 1 1 3 2 3
B 3 2 2 1 3 2
C 1 1 3 2 1 1
B 3 1 1 1 3 2
D 1 3 1 1 1 1
A 1 1 1 3 1 3
B 3 1 1 1 3 1
A B C B(把顺序反过来即可)