1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Giáo trình kỹ thuật lập trình nâng cao phần 2 trường đh công nghiệp thực phẩm tp hcm

39 2 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Nội dung

CHƯƠNG KỸ THUẬT XỬ LÝ CHUỖI Một số khái niệm 4.1 4.1.1 Chuỗi kí tự Chuỗi kí tự, hay cịn gọi xâu kí tự, dãy kí tự viết liền Trong đó, kí tự lấy từ bảng chữ ASCII Chuỗi kí tự hiểu mảng chiều chứa kí tự Cách khai báo chuỗi kí tự sau: char s[100]; char *s = new char[100]; Ví dụ khai báo chuỗi kí tự s có độ dài tối đa 100 kí tự, chuỗi s có tối đa 99 bytes tương ứng 99 kí tự có ý nghĩa chuỗi, byte cuối lưu kí tự kết thúc chuỗi ‘\0’ Kí hiệu ‘\0’ kí tự bắt buộc dùng để kết thúc chuỗi Hằng xâu kí tự ghi cặp dấu nháy kép Ví dụ, “Hello” Nếu cặp dấu nháy kép khơng ghi kí tự ta có chuỗi rỗng độ dài chuỗi rỗng bẳng 4.1.2 Nhập/ xuất chuỗi kí tự Trong ngơn ngữ lập trình C, ta sử dụng hàm scanf với kí tự định dạng %s để nhập chuỗi kí tự người dùng nhập vào từ bàn phím vào chương trình char str[100]; scanf(“%s”, &str); Nhược điểm hàm scanf nhập nội dung chuỗi kí tự có khoảng trắng kết lưu chuỗi khơng người dùng mong muốn Khi nhập chuỗi có chứa kí tự khoảng trằng biên kiểu chuỗi lưu phần đầu chuỗi đến gặp khoảng trắng đầu tiên, phần lại lưu vào vùng nhớ đệm để gán cho biến kiểu chuỗi tiếp sau gặp lệnh scanf dịnh dạng chuỗi lần Thông thường, để nhập chuỗi ký tự từ bàn phím, ta sử dụng hàm gets() Cú pháp: gets() Ví dụ 4.1: char str[100]; gets(str); Để xuất chuỗi (biểu thức chuỗi) lên hình, ta sử dụng hàm puts() Cú pháp: puts() Ví dụ 4.2: puts(str); Một chương trình thực thi sử dụng nhiều biến lưu trữ liệu Trong đó, vùng nhớ chương trình thực thi hạn chế, đó, người dùng thường lưu trữ liệu file text để hỗ trợ cho chương trình thực thi tốt Cho f input file dạng text dòng lệnh f >> s đọc liệu vào đối tượng s đến gặp dấu cách 80 Ví dụ 4.3: Trong file input.txt chứa thông tin sau: 35 11 Đoạn lệnh sau gọi lần dịng lệnh f>>s để thực chức đọc thơng tin file input.txt in nội dung đọc file hình ifstream f(“input.txt”); char s[100]; for(int i=0; i>s; cout tăng j lên Bước 6: I LIKE COMPUTER i=2 83 LIKE j=3 p[j] == T[i+j] = 'I' -> tăng j lên -> j = = m : hết chuỗi P > P có xuất T Kết quả: Xuất vị trí i = vị trí xuất P T 4.2.2 Thuật tóan Knuth – Morris – Pratt Thuật toán Knuth-Morris-Pratt thuật toán có độ phức tạp tuyến tính phát ra, dựa thuật tốn brute force với ý tưởng lợi dụng lại thông tin lần thử trước cho lần sau Trong thuật toán brute force dịch cửa sổ ký tự nên có đến m-1 ký tự cửa sổ ký tự cửa sổ vừa xét Trong có nhiều ký tự so sánh giống với mẫu lại nằm cửa sổ dịch vị trí so sánh với mẫu Việc xử lý ký tự tính tốn trước lưu lại kết Nhờ lần thử sau dịch nhiều ký tự, giảm số ký tự phải so sánh lại Xét lần thử vị trí j, cửa sổ xét bao gồm ký tự y[j…j+m-1] giả sử khác biệt xảy hai ký tự x[i] y[j+i-1] Khi x[1…i]=y[j…i+j-1]=u a=x[i]¹y[i+j]=b Với trường hợp này, dịch cửa sổ phải thỏa mãn v phần đầu xâu x khớp với phần đuôi xâu u văn Hơn ký tự c sau v mẫu phải khác với ký tự a Trong đoạn v thoả mãn tính chất ta quan tâm đến đoạn có độ dài lớn Dịch cửa sổ cho v phải khớp với u c ¹ a Thuật tốn Knuth-Morris-Pratt sử dụng mảng Next[i] để lưu trữ độ dài lớn xâu v trường hợp xâu u=x[1…i-1] Mảng tính trước với chi phí thời gian O(m) (việc tính mảng Next thực chất toán qui hoạch động chiều) Thuật toán Knuth-Morris-Pratt có chi phí thời gian O(m+n) với nhiều 2n-1 lần số lần so sánh ký tự q trình tìm kiếm Ví dụ Để minh họa chi tiết thuật tốn, tìm hiểu q trình thực thuật tốn Ở thời điểm, thuật tốn ln xác định hai biến kiểu nguyên, m i , định nghĩa vị trí tương ứng S bắt đầu cho phép so sánh với W , số W xác định kí tự so sánh Khi bắt đầu, thuật toán xác định sau: m: 84 S: ABC ABCDAB ABCDABCDABDE W: i: ABCDABD Chúng ta tiến hành so sánh kí tự W tương ứng với kí tự S , di chuyển sang chữ chúng giống S[0] W[0] ‘A’ Ta tăng i : m: S: W: i: ABC ABCDAB ABCDABCDABDE ABCDABD _1 S[1] W[1] ‘B’ Ta tiếp tục tăng i : m: S: W: i: ABC ABCDAB ABCDABCDABDE ABCDABD S[2] W[2] ‘C’ Ta tăng i lên : m: S: W: i: ABC ABCDAB ABCDABCDABDE ABCDABD _3 Nhưng, bước thứ tư, ta thấy S[3] khoảng trống W[3] = 'D' , khơng phù hợp Thay tiếp tục so sánh lại vị trí S[1] , ta nhận thấy khơng có kí tự 'A' xuất khoảng từ vị trí đến vị trí xâu S ngồi trừ vị trí 0; đó, nhờ vào q trình so sánh kí tự trước đó, thấy khơng có khả tìm thấy xâu dù có so sánh lại Vì vậy, di chuyển đến kí tự tiếp theo, gán m = i = m: S: ABC ABCDAB ABCDABCDABDE W: i: ABCDABD Tiếp tục trình so sánh trên, ta xác định xâu chung "ABCDAB" , với W[6] ( S[10] ), ta lại thấy không phù hợp Nhưng từ kết trình so sánh trước, ta duyệt qua "AB" , có khả khởi đầu cho đoạn xâu khớp, ta bắt đầu so sanh từ vị trí Như thấy kí tự trùng khớp với hau kí tự phép so khớp trước, không cần kiểm tra lại chúng lần nữa; ta bắt đầu với m = , i = tiếp tục trình so khớp 85 m: S: W: i: ABC ABCDAB ABCDABCDABDE ABCDABD Quá trình so khớp thất bại, W không xuất kí tự ‘ ‘ ,vì vậy, ta tăng m lên 11, gán i = m: S: _11 ABC ABCDAB ABCDABCDABDE W: i: ABCDABD Một lần nữa, hai xâu trùng khớp đoạn kí tự "ABCDAB" kí tự tiếp theo, 'C' , không trùng với 'D' W Giống trước, ta gán m = 15 , gán i = , tiếp tục so sánh m: S: W: i: _15 ABC ABCDAB ABCDABCDABDE ABCDABD Lần này, tìm khớp tương ứng với vị trí bắt đầu S[15] 4.2.3 Thuật tóan Boyer Moore Thuật tốn Boyer Moore thuật tốn có tìm kiếm chuỗi có hiệu thực tiễn, dạng khác thuật toán thường cài đặt chương trình soạn thảo văn Khác với thuật toán Knuth-Morris-Pratt, thuật toán Boyer-Moore kiểm tra ký tự mẫu từ phải sang trái phát khác thuật toán tiến hành dịch cửa sổ Trong thuật toán có hai cách dịch sổ: Cách thứ 1: gần giống cách dịch thuật toán KMP, dịch cho phần so sánh lần trước khớp với phần giống lần sau Trong lần thử vị trí j, so sánh đến ký tự i mẫu phát khác nhau, lúc x[i+1…m]=y[i+j j+m-1]=u a=x[i]¹y[i+j-1]=b thuật toán dịch cửa sổ cho đoạn u=y[i+j…j+m-1] giống với đoạn mẫu (trong phép dịch ta chọn phép dịch nhỏ nhất) Nếu khơng có đoạn nguyên vẹn u xuất lại x, ta chọn cho phần đôi dài u xuất trở lại đầu mẫu 86 Cách thứ 2: Coi ký tự không khớp văn b=y[i+j-1] ta dịch cho có ký tự giống b xâu mẫu khớp vào vị trí (nếu có nhiều vị trí xuất b xâu mẫu ta chọn vị trí phải nhất) Nếu khơng có ký tự b xuất mẫu ta dịch cửa sổ cho ký tự trái cửa sổ vào vị trí sau ký tự y[i+j-1]=b để đảm bảo ăn khớp Trong hai cách dịch thuật tốn chọn cách dịch có lợi Trong cài đặt ta dùng mảng bmGs để lưu cách dịch 1, mảng bmBc để lưu phép dịch thứ 2(ký tự khơng khớp) Việc tính tốn mảng bmBc thực khơng có nhiều để bàn Nhưng việc tính trước mảng bmGs phức tạp, ta khơng tính trực tiếp mảng mà tính gián tiếp thơng qua mảng suff Có suff[i]=max{k | x[i-k+1…i]=x[mk+1…m]} Các mảng bmGs bmBc tính tốn trước thời gian tỉ lệ với O(m+d) Thời gian tìm kiếm (độ phức tạp tính tốn) thuật tốn Boyer-Moore O(m*n) Tuy nhiên với chữ lớn thuật toán thực nhanh Trong trường hợp tốt chi phí thuật tốn xuống đến O(n/m) chi phí thấp thuật tốn tìm kiếm đại đạt 87 BÀI TẬP CHƯƠNG Bài Cho file input.txt chứa nội dung sau: Môn học: Kỹ thuật lập trình nâng cao Số tiết: 30 Viết chương trình đọc nội dung file input.txt hình theo định dạng file Bài Cho file input.txt chứa nội dung sau: 35 12 Viết chương trình đọc nội dung file input.txt lưu vào mảng chiều, sau in hình tổng phần tử mảng Bài Cho file input.txt chứa nội dung sau: Số phần tử là: Giá trị mảng la: 13 Viết chương trình đọc nội dung file input lưu vào biến mảng chiều, xếp mảng chiều tăng dần, sau lưu kết mảng xếp vào file output.txt Bài Cho file input chứa nội dung sau: Số dòng: Số cột: -5 12 21 -45 19 -7 Viết chương trình đọc nội dung file input lưu vào biến mảng chiều, tìm dịng có tổng lớn nhất, sau lưu kết vào file output.txt Bài Cho file input.txt chứa nội dung sau: Số phần tử: 9 Viết chương trình đọc nội dung file input, đếm số phần tử chẵn biên ma trận, sau in kết hình Bài Cho file input.txt chứa nội dung sau: Số phần tử: 88 Ma trận A Ma trận B Viết chương trình đọc nội dung file input, tính ma trận tổng S = A+B, ma trận tích P = AxB, sau lưu ma trận kết vào file output.txt Bài Viết chương trình cài đặt thuật tốn tìm chiều dài xâu chung dài chuỗi ký tự cho trước Bài Viết chương trình cài đặt thuật tốn tìm kiếm chuỗi Brute Force Bài Viết chương trình cài đặt thuật tốn tìm kiếm chuỗi Knuth – Morris – Pratt Bài 10 Viết chương trình cài đặt thuật tốn tìm kiếm chuỗi Boyer – Moore 89 - Sự kết hợp lời giải toán chưa cho ta lời giải toán ban đầu Sau số tốn điển hình giải kỹ thuật quy hoạch động 5.4.2 Một số tốn minh họa 5.4.2.1 Bài tốn tính số tổ hợp Một tốn quen thuộc tính số tổ hợp chập k n theo công thức truy hồi: = ế = ℎ ặ = + ế < < Dựa vào công thức truy hồi trên, có giải thuật đệ quy cho toán sau : int TinhToHop (int n, int k) { if(k==0 || k==n) return 1; else return TinhToHop (n-1,k-1) + TinhToHop (n-1,k); } Gọi T(n) thời gian để tính số tổ hợp chập k n, ta có phương trình đệ quy: T(1) = C1 T(n) = 2T(n-1) + C2 n Giải phương trình ta T(n) = O(2 n ), giải thuật thời gian mũ, có đa thức tốn Ðiều chứng tỏ có tốn giải nhiều lần Chẳng hạn để tính TinhToHop (4,2) ta phải tính TinhToHop (3,1) TinhToHop (3,2) Ðể tính TinhToHop (3,1) ta phải tính TinhToHop (2,0) TinhToHop (2,1) Ðể tính TinhToHop (3,2) ta phải tính TinhToHop (2,1) TinhToHop (2,2) Như để tính TinhToHop (4,2) ta phải tính TinhToHop (2,1) hai lần Hình Sơ đồ thực tinhToHop(4,2) Áp dụng kĩ thuật quy hoạch động để khắc phục tình trạng trên, ta xây dựng bảng gồm n+1 dòng (từ đến n) n+1 cột (từ đến n) điền giá trị cho O(i,j) theo quy tắc sau: (Quy tắc tam giác Pascal): 104 – C(0,0) = 1; – C(i,0) =1; – C(i,i) = với < i  n; – C(i,j) =C(i-1,j-1) + C(i-1,j) với < j < i  n Với O(n,k) tinhToHop (n,k) Cụ thể với n=4 ta có bảng sau : j i 1 1 2 3 4 Giải thuật quy hoạch động tốn tính tổ hợp : int tinhToHop_DP (int n, int k) { int C[n+1][n+1]; /*1*/ C[0][0] = 1; /*2*/ for (int i = 1; i

Ngày đăng: 30/06/2023, 09:52

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN