Bai2.inp | Bai2.inp |
Ky thi hoc sinh gioi Tinh mon tin hoc hoc sinh gioi mon Tin hoc |
14 |
Const fi='Bai2.inp';
fo='Bai2.out';
var S1,S2: string;
i,j,l1,l2,k,kmax:byte;
procedure doctep;
var f:text;
begin
assign(f,fi);
reset(f);
readln(f,s1);
readln(f,s2);
close(f);
end;
procedure capnhat;
begin
if kmax < k then kmax:=k;
end;
procedure xuly;
begin
l1:=length(s1);
l2:=length(s2);
k:=0;
kmax:=0;
for i:=1 to l1 do
for j:=1 to l2 do
if s1[i]=s2[j] then
begin
k:=1;
while (i+k<=l1) and (j+k<=l2) and (s1[i+k]=s2[j+k]) do inc(k);
capnhat;
end;
end;
procedure ghitep;
var f:text;
begin
assign(f,fo);
rewrite(f);
writeln(f,kmax);
close(f);
end;
BEGIN
DOCTEP;
XULY;
GHITEP;
END.
Để viết theo quy hoạch động ta tạo một mảng 2 chiều dp (Có số cột chính là độ dài của xâu s1; Có số hàng chính là độ dài của xâu s2). Mảng này sẽ lưu lại độ dài của các xâu con chung. Như vậy thì giá trị tạo cột`i`
, hàng `j`
sẽ là `dp[i][j]`
đại diện cho độ dài của xâu con chung liên tiếp dài nhất, kết thúc tại ký tự thứ `i`
của xâu `s1`
và ký tự thứ `j`
của xâu `s2`
. Với mỗi ô `(i, j)`
trong ma trận, nếu ký tự tại vị trí `i`
của xâu `s1`
bằng ký tự tại vị trí `j`
của xâu `s2`
thì ta gán `dp[i][j] = dp[i-1][j-1] + 1`
, tức là tăng giá trị của `dp[i][j]`
lên 1 so với ô ở phía trước đó, đồng thời lúc này ta so sánh `dp[i][j]`
với `max`
để cập nhật lại giá trị `max`
để lưu độ dài xâu con chung dài nhất. Nếu không, `dp[i][j]`
sẽ bằng 0. Bài toán này không yêu cầu in ra dãy con chung dài nhất nên ta không cần truy vết, lúc đó ta sẽ code như sau:
# Đọc dữ liệu từ file input
with open("Bai2.inp", "r") as f:
s1 = f.readline().strip()
s2 = f.readline().strip()
# Tạo bảng để lưu độ dài của xâu con chung
dp = [[0] * (len(s2) + 1) for _ in range(len(s1) + 1)]
max=0
# Duyệt qua các phần tử của 2 xâu và tính độ dài xâu con chung tại mỗi ô của bảng
for i in range(1, len(s1) + 1):
for j in range(1, len(s2) + 1):
if s1[i - 1] == s2[j - 1]: # Nếu hai ký tự giống nhau
dp[i][j] = dp[i - 1][j - 1] + 1 # Cộng thêm 1 vào độ dài của xâu con chung
if dp[i][j]>max:
max=dp[i][j] # Cập nhật lại max.
# In ra độ dài của xâu con chung dài nhất
with open("Bai2.out", "w") as f:
f.write(str(max))
`max`
thay đổi. Ta sẽ khởi tạo thêm 2 biến `start_index=None`
và `end_index=None`
. Và ta sẽ gán `start_index =
i - max`
và `start_index = i - 1
`
mỗi khi `max
`
thay đổi.
# Đọc dữ liệu từ file input
with open("Bai2.inp", "r") as f:
s1 = f.readline().strip()
s2 = f.readline().strip()
# Tạo bảng để lưu độ dài của xâu con chung
dp = [[0] * (len(s2) + 1) for _ in range(len(s1) + 1)]
start_index = None # index bắt đầu của xâu con chung liên tiếp dài nhất
end_index = None # index kết thúc của xâu con chung liên tiếp dài nhất
max=0 # Độ dài xâu con chung dài nhất
# Duyệt qua các phần tử của 2 xâu và tính độ dài xâu con chung tại mỗi ô của bảng
for i in range(1, len(s1) + 1):
for j in range(1, len(s2) + 1):
if s1[i - 1] == s2[j - 1]: # Nếu hai ký tự giống nhau
dp[i][j] = dp[i - 1][j - 1] + 1 # Cộng thêm 1 vào độ dài của xâu con chung
if dp[i][j]>max:
max=dp[i][j] # Cập nhật lại max
start_index = i - max
end_index = i - 1
# In ra độ dài của xâu con chung dài nhất
with open("Bai2.out", "w") as f:
f.write(str(max))
# In xâu con lớn nhất ra màn hình
if max!=0:
print(s1[start_index:end_index+1])
else: print('Không co xâu chung nào')
Tác giả: admin
Ý kiến bạn đọc