求最长公共子序列(lcs.pas/c/cpp)
字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序 列 Y=“y0,y1,…,yk-1”是 X的子序列,存在X 的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的 j=0,1,…,k-1,有 xij = yj。例如,X=“ABCBDAB”,Y=BCDB”是 X 的一个子序列。
对给定的两个字符序列,求出他们最长的公共子序列。
输入数据:
第 1行为第 1 个字符序列,都是大写字母组成,以”.”结束。长度小于5000。
第 2行为第 2 个字符序列,都是大写字母组成,以”.”结束,长度小于5000。
输出数据:
输出上述两个最长公共自序列的长度。
样例:
lcs.in
ABCBDAB.
BACBBD.
lcs.out
4
======================
O(N^2)算法...
f[i,j]表示第一行前i个,第二行前j个最多有多少个相等...
if st1[i]=st2[j] then f[i,j]:=max(f[i,j],f[i-1,j-1]+1)
==================================
var
st1,st2:ansistring;
f:array[0..5000,0..5000]of longint;
procedure init;
begin
assign(input,'lcs.in');
assign(output,'lcs.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
procedure main;
var
i,j:longint;
ans,len1,len2:longint;
begin
fillchar(f,sizeof(f),0);
readln(st1);
readln(st2);
st1:=copy(st1,1,length(st1)-1);
st2:=copy(st2,1,length(st2)-1);
ans:=0;
// writeln(st1[1]);
len1:=length(st1);
len2:=length(st2);
for i:=1 to length(st1) do
for j:=1 to length(st2) do
begin
//writeln(st1[i],' ',st2[j]);
//writeln(f[i,j],' ',f[i-1,j-1]);
f[i,j]:=max(f[i,j],f[i,j-1]);
f[i,j]:=max(f[i,j],f[i-1,j]);
//f[i,j]:=max(f[i,j],f[i,j-1]);
//f[i,j]:=max(f[i,j],f[i-1,j]);
if st1[i]=st2[j] then
f[i,j]:=max(f[i,j],f[i-1,j-1]+1);
if ans<f[i,j] then ans:=f[i,j];
//writeln(f[i,j],' ',f[i-1,j-1]);
//writeln;
end;
writeln(ans);
end;
begin
init;
main;
terminate;
end.
====================
变:若要求最长公共子串
{
ID:jie19952
PROG:
LANG:PASCAL
}
var
st1,st2:string;
f:array[0..200,0..200]of string;
procedure init;
begin
assign(input,'lcs.in');
assign(output,'lcs.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
function js(i,j:longint):longint;
begin
js:=0;
if st1[i]=st2[j] then exit(1);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
procedure main;
var
i,j:longint;
begin
readln(st1); readln(st2);
fillchar(f,sizeof(f),0);
for i:=1 to length(st1) do
for j:=1 to length(st2) do
begin
if length(f[i,j])<length(f[i-1,j]) then f[i,j]:=f[i-1,j];
if length(f[i,j])<length(f[i,j-1]) then f[i,j]:=f[i,j-1];
if js(i,j)<>0 then
if length(f[i,j])<length(f[i-1,j-1])+js(i,j) then f[i,j]:=f[i-1,j-1]+st1[i];
end;
writeln(length(f[length(st1),length(st2)]));
writeln(f[length(st1),length(st2)]);
end;
begin
init;
main;
terminate;
end.