Sáng tạo trong thuật toán và lập trình với ngôn ngữ Pascal và C# - Tập 1 - Chương 4: Tổ chức dữ liệu

Giả sử xâu s chứa biểu thức cần xử lí. Ta duyệt lần lượt từ đầu đến cuối xâu s, với

mỗi kí tự s[i] ta xét hai trường hợp:

 Trường hợp thứ nhất: s[i] là dấu mở ngoặc '(': ta ghi nhận i là vị trí

xuất hiện đầu cụm vào một ngăn xếp (stack) st:

inc(p); st[p] := i;

trong đó p là con trỏ ngăn xếp. p luôn luôn trỏ đến ngọn, tức là phần tử cuối

cùng của ngăn xếp. Thủ tục này gọi là nạp vào ngăn xếp: NapST.

pdf41 trang | Chuyên mục: Pascal | Chia sẻ: dkS00TYs | Lượt xem: 2071 | Lượt tải: 2download
Tóm tắt nội dung Sáng tạo trong thuật toán và lập trình với ngôn ngữ Pascal và C# - Tập 1 - Chương 4: Tổ chức dữ liệu, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
t tổ chức hậu tố như sau. 
Hậu tố của một xâu là đoạn cuối của xâu đó. Như vậy một xâu có chiều dài n sẽ có 
n hậu tố. Thí dụ, với xâu mẫu s[1..10] = 'cabxabcdab' ta có 10 hậu tố sau 
đây: 
s[1..10] = 'cabxabcdab' 
s[2..10] = 'abxabcdab' 
s[3..10] = 'bxabcdab' 
s[4..10] = 'xabcdab' 
s[5..10] = 'abcdab' 
s[6..10] = 'bcdab' 
s[7..10] = 'cdab' 
s[8..10] = 'dab' 
s[9..10] = 'ab' 
s[10..10] = 'b' 
Như vậy, hậu tố sau sẽ nhận được từ hậu tố sát trước nó bằng cách bỏ đi kí tự 
đầu tiên. 
Trước hết ta sắp tăng các hậu tố của xâu mẫu s theo trật tự từ điển. Sử dụng một 
mảng chỉ dẫn id, trong đó id[i] trỏ đến vị trí đầu tiên của hậu tố trong xâu mẫu. Cụ thể 
là, nếu id[i] = k thì hậu tố tương ứng sẽ là s[k..n]. Sau khi sắp tăng các hậu tố của xâu 
mẫu s[1..10] = 'cabxabcdab' ta thu được: 
i id[i] Hậu tố Xâu 
1 9 S[9..10] ab 
2 5 S[5..10] abcdab 
3 2 S[2..10] abxabcdab 
4 10 S[10..10] b 
5 6 S[6..10] bcdab 
6 3 S[3..10] bxabcdab 
7 1 S[1..10] cabxabcdab 
8 7 S[7..10] cdab 
 9 8 S[8..10] dab 
10 4 S[4..10] xabcdab 
Sắp tăng theo chỉ dẫn các hậu tố của xâu 
s[1..10] = 'cabxabcdab' 
Việc còn lại là so sánh xâu x với các hậu tố s[i..j] để tìm khúc đầu chung dài nhất 
giữa chúng. Thí dụ, với x[1..4]='abcd' thì khúc đầu chung dài nhất tìm được với 
hậu tố s[5..10] do id[2] trỏ tới. Vị trí v tìm được sẽ là 5 và chiều dài lớn nhất d sẽ là 4. 
Phần chính của chương trình sẽ như sau: 
procedure Run; 
begin 
... 
n:= length(s); 
Sáng tạo trong Thuật toán và Lập trình Tập I 
122 
for i:=1 to n do id[i]:=i; 
IdQuikSort(1,n); 
while not seekeof(f) do 
begin 
 readln(f,x); 
 writeln(g,x); 
 Tim; {xac dinh v và d} 
 writeln(g,v,BL,d); 
end; 
end; 
Để ý rằng với mỗi xâu x, nếu phần tử đầu tiên của x là x[1] không trùng với phần tử 
đầu tiên của hậu tố h thì chiều dài của khúc đầu chung của chúng sẽ bằng 0. Nhờ nhận 
xét này và do dãy các hậu tố đã được sắp tăng nên với mỗi xâu x, trước hết ta gọi hàm 
Binsearch để thực hiện tìm kiếm nhị phân phần tử x[1] trong dãy gồm các phần tử 
đầu tiên của các hậu tố, sau đó ta thực hiện việc duyệt tìm. 
procedure Tim; 
var 
 i,Len: integer; 
begin 
v:=BinSearch; d := 0; 
if v=0 then exit; 
Maxlen:=0; 
for i:=v to n do 
begin 
 if s[id[i]]x[1] then exit; 
 Len:=Eqsx(id[i]); 
 if Len > d then 
 begin 
 d:=Len; 
 v:=id[i]; 
 end; 
end; 
end; 
Hàm BinSearch sẽ cho ra chỉ dẫn tới hậu tố h đầu tiên thoả điều kiện h[1] = 
x[1]. 
(*--------------------------------- 
 Tim xuat hien cua x[1]trong day 
 da sap cac hau to 
---------------------------------*) 
function BinSearch:integer; 
var 
 d,c,m: integer; 
begin 
d:=1; 
c:=n; 
repeat 
m:=(d+c) div 2; 
if x[1]>s[id[m]] then d:=m+1 
else c:=m; 
until d=c; 
Sáng tạo trong Thuật toán và Lập trình Tập I 
123 
if x[1]s[id[d]] then Binsearch := -1 
else BinSearch := d; 
end; 
Hàm Eqsx(i) cho ta chiều dài lớn nhất của khúc đầu chung giữa hậu tố s[i..n] và 
xâu x. 
(*--------------------------------- 
 Khuc dau dai nhat giua 
 hau to s[i..n] va x 
---------------------------------*) 
function Eqsx(i:integer): integer; 
var 
 k,m:integer; 
begin 
m:=min(length(x),n-i+1); 
for k:=1 to m do 
 if s[i+k-1]x[k] then 
 begin 
 Eqsx:=k-1; 
 exit; 
 end; 
Eqsx:=m; 
end; 
(* Pascal *) 
(*---------------------- 
 STRINGS: Xau mau 
------------------------*) 
program Strings; 
{$B-} 
uses crt; 
const 
 MN = 255; 
 cd = #0; {ki tu trong} 
 cc = #255; {ki tu cuoi cua bang ma ASCII} 
 BL=#32; {dau cach} 
 fn = 'strings.inp'; {tep vao} 
 gn = 'strings.out'; {tep ra} 
type 
 mb1 = array[0..MN] of integer; 
var 
 f,g: text; 
 s,x: string; {s: xau mau} 
 id: mb1; {chi dan} 
 n: integer; {chieu dai xau mau s} 
 v,d: integer; 
 {v: vi tri xuat hien khuc dau cua x trong xau mau s} 
 {d: maxlen} 
(*------------------------------- 
 min cua 2 phan tu 
--------------------------------*) 
Sáng tạo trong Thuật toán và Lập trình Tập I 
124 
function min(a,b:integer):integer; 
begin 
if a<=b then min:=a 
else min:=b; 
end; 
(*------------------------------- 
Tim xuat hien cua x[1] trong day da sap cac hau to 
-------------------------------*) 
function BinSearch:integer; 
var 
 d,c,m: integer; 
begin 
d:=1; 
c:=n; 
repeat 
m:=(d+c) div 2; 
if x[1]>s[id[m]] then d:=m+1 
else c:=m; 
until d=c; 
if x[1]s[id[d]] then Binsearch:=0 
else BinSearch:=d; 
end; 
(*-------------------------------------- 
 so sanh 2 hau to trong s: 
 s[i..n] va s[j..n] 
---------------------------------------*) 
function sanh(i,j:integer):integer; 
var k:integer; 
begin 
for k:=0 to min(n-i,n-j) do 
if s[i+k]s[j+k] then 
begin 
if s[i+k]<s[j+k] then sanh:=-1 
else sanh:=1; 
exit; 
end; 
if i=j then sanh:=0 
 else if i<j then sanh:=1 
else sanh:=-1; 
end; 
(*------------------------------------- 
 Quick sort cac hau to theo chi dan 
-------------------------------------*) 
procedure IdQuickSort(d,c: integer); 
var i,j,m,t: integer; 
begin 
i:=d; {dau} 
j:=c; {cuoi} 
m:=id[(i+j) div 2]; {phan tu giua} 
while i<=j do 
begin 
Sáng tạo trong Thuật toán và Lập trình Tập I 
125 
 while sanh(id[i],m)<0 do inc(i); 
 while sanh(id[j],m)>0 do dec(j); 
 if (i<=j) then 
 begin 
 t:=id[i]; 
 id[i]:=id[j]; 
 id[j]:=t; 
 inc(i); dec(j); 
 end; 
end; 
if d<j then IdQuickSort(d,j); 
if i<c then IdQuickSort(i,c); 
end; 
(*------------------------------------------ 
 Khuc dau dai nhat giua hau to s[i..n] va x 
-------------------------------------------*) 
function Eqsx(i:integer): integer; 
var k,m:integer; 
begin 
m:=min(length(x),n-i+1); 
for k:=1 to m do 
if s[i+k-1]x[k] then 
begin 
Eqsx:=k-1; 
exit; 
end; 
Eqsx:=m; 
end; 
(*-------------------------------------------- 
Tim vi tri va chieu dai lon nhat 
MaxLen giua cac hau to cua xau mau s va xau x 
---------------------------------------------*) 
procedure Tim; 
var i,Len: integer; 
begin 
v:=BinSearch; 
d:=0; 
if v=0 then exit; 
for i:=v to n do 
begin 
 if s[id[i]]x[1] then exit; 
 Len:=Eqsx(id[i]); 
 if Len > d then 
 begin 
 d:=Len; 
 v:=id[i]; 
 end; 
end; 
end; 
procedure Run; 
Sáng tạo trong Thuật toán và Lập trình Tập I 
126 
var i:integer; 
begin 
assign(f,fn); 
reset(f); 
assign(g,gn); 
rewrite(g); 
readln(f, s); 
writeln(g,s); 
n:= length(s); 
for i:=1 to n do id[i]:=i; 
IdQuickSort(1,n); 
while not seekeof(f) do 
begin 
readln(f,x); 
writeln(g,x); 
Tim; 
writeln(g,v,BL,d); 
end; 
close(f); 
close(g); 
end; 
BEGIN 
Run; 
END. 
Dữ liệu kiểm thử 
STRINGS.INP 
Kết quả dự kiến 
STRINGS.OUT 
cabxabcdab 
abcd 
cdaeh 
cabxabcdab 
abcd 
5 4 
cdaeh 
7 3 
// C# 
using System; 
using System.IO; 
namespace SangTao1 
{ 
 /*------------------------ 
 * Xau mau 
 * ----------------------*/ 
 class Strings 
 { 
 const string fn = "strings.inp"; 
 const string gn = "strings.out"; 
 static string s; // xau mau 
 static string x; // xau can xu ly 
Sáng tạo trong Thuật toán và Lập trình Tập I 
127 
 static int[] id; 
static int v = 0;// vi tri xuat hien khuc dau x trg s 
 static int d = 0;// chieu dai x trong s 
 static int n = 0; // chieu dai xau mau 
 static void Main() 
 { 
 Run(); 
 Test(); 
 Console.ReadLine(); 
 } // Main 
 // Doc lai file gn de kiem tra ket qua 
 static void Test() 
 { 
 Console.WriteLine("\n Kiem tra lai ket qua \n\n"); 
 Console.WriteLine("\n Input: " + 
 File.ReadAllText(fn)); 
 Console.WriteLine("\n Output: " + 
 File.ReadAllText(gn)); 
 } 
 static void Run() 
 { 
 StreamReader f = File.OpenText(fn); 
 StreamWriter g = File.CreateText(gn); 
 // Bo qua cac dong trong dau tien 
 while ((s = (f.ReadLine()).Trim()) == "") ; 
 n = s.Length; // Len xau mau 
 id = new int[n]; 
 // Khoi tri cho index 
 for (int i = 0; i < n; ++i) id[i] = i; 
 IdQSort(0, n - 1); 
 Console.WriteLine(" Xau mau: " + s + "\n\n"); 
 SPrint(); 
 g.WriteLine(s); 
 while ((x = f.ReadLine()) != null) 
 { 
 x = x.Trim(); 
 if (x != "") 
 { 
 Console.WriteLine(x); 
 g.WriteLine(x); 
 Find(); 
 g.WriteLine(v + " " + d); 
 } 
 } 
Sáng tạo trong Thuật toán và Lập trình Tập I 
128 
 f.Close(); g.Close(); 
 } 
 static void Find() 
 { 
 v = BinSearch(x[0]);// hau to co ki tu dau la x[0] 
 d = 0; 
 if (v < 0) return; 
 for (int i = v; i < n; ++i) 
 { 
 int j = id[i]; 
 if (s[j] != x[0]) return; 
 int k = ComLen(x, j); 
 if (d < k) { v = j + 1; d = k;} 
 } 
 } 
 // MaxLen khuc dau cua x va hau to s[j... 
 static int ComLen(string x, int j) 
 { 
 int minlen = Min(x.Length, n - j); 
 for (int i = 0; i < minlen; ++i) 
 if (x[i] != s[j + i]) return i; 
 return minlen; 
 } 
 static int Min(int a, int b) 
 { return (a < b) ? a : b;} 
 static int BinSearch(char c) 
 { 
 int i = 0; 
 int j = n - 1; 
 int m = 0; 
 while (i < j) 
 { 
 m = (i + j) / 2; 
 if (s[id[m]] < c) i = m + 1; 
 else j = m; 
 } 
 return (s[id[i]] == c) ? i : -1; 
 } 
 // Hien thi day duoc sap cac hau to 
 // cua s de kiem tra 
 static void SPrint() 
 { 
 Console.WriteLine("\n Cac hau to sap tang: \n"); 
 for (int i = 0; i < n; ++i) 
 Console.WriteLine(s.Substring(id[i], n - id[i])); 
Sáng tạo trong Thuật toán và Lập trình Tập I 
129 
 } 
 static void IdQSort(int d, int c) 
 { 
 int i = d; 
 int j = c; 
 int m = id[(i + j) / 2]; 
 int t = 0; 
 while (i <= j) 
 { 
 while (Sanh(id[i], m) < 0) ++i; 
 while (Sanh(m, id[j]) < 0) --j; 
 if (i <= j) 
 { 
 t = id[i]; id[i] = id[j]; id[j] = t; 
 ++i; --j; 
 } 
 } 
 if (d < j) IdQSort(d, j); 
 if (i < c) IdQSort(i, c); 
 } 
 static int Sanh(int x, int y) 
 { 
 int ix = 0; 
 int iy = 0; 
 for (int i = 0; i < n; ++i) 
 { 
 ix = (x + i) % n; 
 iy = (y + i) % n; 
 if (s[ix] != s[iy]) 
 return (s[ix] < s[iy]) ? -1 : 1; 
 } 
 return 0; 
 } 
 } // Strings 
} // SangTao1 
CHƢƠNG 5 
PHƢƠNG PHÁP THAM LAM 

File đính kèm:

  • pdfSáng tạo trong thuật toán và lập trình với ngôn ngữ Pascal và C# - Tập 1 - Chương 4_Tổ chức dữ liệu.pdf