Tải bản đầy đủ (.docx) (3 trang)

Quy hoạch động Bài toán Palindrome

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (214.48 KB, 3 trang )

Tài liệu bồi dưỡng học sinh giỏi THPT – Môn Tin học

Phần II: Chuyên đề nâng cao

CHUYÊN ĐỀ NÂNG CAO 6

CHUYÊN ĐỀ 6: QUY HOẠCH ĐỘNG
D. BÀI TOÁN XÂU PALINDROME (XÂU ĐỐI XỨNG)
Palindrome hay còn gọi là xâu đối xứng, xâu đối gương là tên gọi của những xâu kí tự mà khi viết
từ phải qua trái hay từ trái qua phải thì xâu đó không thay đổi.
VD: MADAM, IOI,... Nhờ tính chất đặc biệt đó mà có khá nhiều bài tập có liên quan đến
Palindrome, phần lớn trong chúng thường đi kèm với QHĐ.
Bài 1: Xem một xâu có phải là Palindrome hay không?
Đây là một bài cơ bản, nhưng quan trọng vì nó được đề cập đến trong nhiều bài tập khác. Cách
làm tốt nhất là duyệt đơn thuần mất O(N).
Ý tưởng: Chương trình con kiểm tra đối xứng
IsPalin(S):boolean;




n = length(s)
Duyệt từ 1 đến n div 2: Nếu S[i]<>S[n-i+1]
Exit(True);

thì Exit(False);

Giải thích:
Ta kiểm tra từ đầu đến ½ xâu S: Nếu gặp cặp kí tự nào khác nhau tức là xâu S ko đối xứng: Khi
đó ta kết thúc chương trình và cho kết quả là False
- Còn nếu sau khi duyệt mà ko dừng tức là đối xứng: kết thúc và cho kết quả True.


Bài 2: Palindrome liên tiếp dài nhất
Cho một xâu S <= 1000 kí tự; tìm palindrome dài nhất là xâu con của S (Xâu con là một dãy các kí tự liên
tiếp).
Cách 1: Duyệt trâu: ta sẽ kiểm tra từng đoạn con của xâu S
Ý tưởng: Ta sẽ dùng vòng lặp để tìm đoạn Palin dài nhất
-

-

Smax = ‘’
Kiểm tra tất cả các xâu con: Nếu xâu nào là palin thì so sánh
mới smax và lưu lại.

Code:
For i:=1 to n-1 do
For j:=i+1 to n do nếu Ispalin(sij) và sij dài hơn Smax thì smax=sij
Độ phức tạp: 2 vòng for là O(n 2) thêm ispalin là O(n) vậy độ phức tạp là O(n 3).

Với cách 1 này: Khi s khoảng 1000 kí tự thì thời gian chạy chương trình sẽ rất lớn, không đáp ứng được
yêu cầu.
Cách 2: QHĐ
Dùng mảng L[i, j] có ý nghĩa: L[i, j] = true nếu đoạn gồm các kí tự từ i đến j của S là palindrome.
Ta có công thức là:
L[i, i] = True
L[i, j] = L[i+1, j-1]; ( nếu s[i] = s[j] )
L[i, j] = False; ( nếu s[i] <> s[j] )

Đoạn chương trình như sau:
for i:=1 to n do L[i,i]:=true;
for j:=2 to n do

for i:=1 to j-1 do
if s[i]<>s[j]
then L[i,j]:= false
else L[i,j]:=(i+1=j) or L[i+1,j-1];

Kết quả là : Max(j-i+1) <=j thỏa F[i,j] = True.
• Độ phức tạp thuật toán là 0(N^2).
Thuật toán tốt hơn cho bài này: Các em có thể tìm đọc thêm thuật toán manacher.
Giáo viên: Lê Thanh Phú

1|Tra n g




Tài liệu bồi dưỡng học sinh giỏi THPT – Môn Tin học

Phần II: Chuyên đề nâng cao

Bài trên còn có một cách NlogN nữa là dùng Suffix Aray, thậm chí có cách O(N) là sử dụng Suffix Tree và
thuật toán tìm LCA. Đương nhiên cách cài đặt không hề dễ dàng.
Bài 3: Chia Xâu thành các đoạn palindrome
Chia một xâu thành ít nhất các Palindrome (độ dài <=1000). Bài này phức tạp hơn bài trên, cách
làm thì vẫn là QHĐ.
Gọi F[i] là số palindrome ít nhất mà đoạn 1..j chia thành được.
Ta có công thức:
F[i] = max( F[j] + 1; "j < i thỏa mãn: đoạn j+1..i là palindrome)
Kết quả là F[n]

Đoạn chương trình như sau:

for i:=1 to n do f[i]:=n;
for i:=1 to n do
for j:=i-1 downto 0 do
if L[j+1,i] then F[i]:=min(f[i],f[j]+1);

Hai vòng for lồng nhau mất O(N^2)
Mảng L[i, j] có ý nghĩa tương tự bài 2.
Bài 4: Pal - Ioicamp – Có bao nhiêu xâu con là Palindrome
Cho một xâu, hỏi nó có bao nhiêu xâu con là palindrome; xâu con ở đây gồm các kí tự không cần liên tiếp
( độ dài <= 120 ).
Pal.iinp
IOICAMP

Pal.out
9

Đây là một bài tập rất thú vị. Phương pháp là dùng QHĐ.
Gọi F[i, j] là số palindrome là xâu con của đoạn i..j.
Ta có công thức :




F[i, i] = 1;
Nếu s[i] = s[j]
Nếu s[i] <> s[j]

thì f[i,j]=f[i+1,j]+f[i,j-1]+1
thì f[i,j]=f[i+1,j]+f[i,j-1]-f[i+1,j-1];


Đoạn chương trình như sau :
//QHD: f[i,j] la so luong palindrome trong doan i..j
for i:=1 to n do f[i,i]:=1;
for j:=2 to n do
for i:=j-1 downto 1 do
if s[i]=s[j] then f[i,j]:=f[i+1,j]+f[i,j-1]+1
else f[i,j]:=f[i,j-1]+f[i+1,j]-f[i+1,j-1];
write(f[1,n]);

Độ phức tạp của thuật toán là O(N2). Vì vậy, chúng ta hoàn toàn có thể làm với N = 1000.
Bài 5: Thêm vào ít kí tự nhất để thành xâu Palindrome
Cho một xâu, hỏi phải thêm vào nó ít nhất bao nhiêu xâu kí tự để nó trở thành một palindrome (độ dài
<= 500).
Bài này cũng sử dụng QHĐ:
Gọi F[i, j] là số phép biến đổi ít nhất cần thêm vào đoạn i..j để đoạn i..j trở thành palindrome.
Ta có công thức :
-

F[i, i] = 0;
Nếu s[i] = s[j] thì F[i, j] = F[i+1, j-1]
Nếu s[i] <> s[j] thì F[i, j] = Min( F[i, j-1], F[i+1, j] ) + 1;

Đoạn chương trình:
for i:=1 to n do f[i,i]:=0;

Giáo viên: Lê Thanh Phú

2|Tra n g





Tài liệu bồi dưỡng học sinh giỏi THPT – Môn Tin học
Phần II: Chuyên đề nâng cao
for j:=2 to n do
for i:=j-1 downto 1 do
if s[i]<>s[j] then f[i,j]:=min(f[i,j-1],f[i+1,j])+1
else f[i,j]:=f[i+1,j-1];
write(f[1,n]);

Bài 6: The next palindrome - SPOJ
Cho nhiều số <= 106, với mỗi số, tìm số bé nhất có dạng palindrome lớn hơn số đã cho.
Ví Dụ :
NextPalin.inp
NextPalin.out
2
818
808
2222
2133
[i]Gợi ý: dùng phương pháp đếm kết hợp QHĐ

Giáo viên: Lê Thanh Phú

3|Tra n g






×