Tải bản đầy đủ (.pdf) (31 trang)

Tài Liệu Phương Pháp Giải Một Số Bài Toán Chuỗi Con Bằng Ngôn Ngữ Lập Trình C++.Pdf

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 (829.52 KB, 31 trang )

1 of 98.

1
SỞ GIÁO DỤC & ĐÀO TẠO NGHỆ AN
TRƢỜNG THPT KIM LIÊN

SÁNG KIẾN KINH NGHIỆM
Đề tài:
“PHƢƠNG PHÁP GIẢI MỘT SỐ BÀI TOÁN CHUỔI
CON BẰNG NNLT C++”
Lĩnh vực: Tin học

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


2 of 98.

2
SỞ GIÁO DỤC & ĐÀO TẠO NGHỆ AN
TRƢỜNG THPT KIM LIÊN

SÁNG KIẾN KINH NGHIỆM
Đề tài:
“PHƢƠNG PHÁP GIẢI MỘT SỐ BÀI TOÁN CHUỔI
CON BẰNG NNLT C++”
Lĩnh vực: Tin học

Giáo viên: Nguyễn Quang Hùng – Nguyễn Thị Lƣu
Trƣờng THPT Kim Liên
Năm học: 2022-2023
Số điện thoại: 0973484114 - 0914527656



Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


3 of 98.

1
MỤC LỤC

PHẦN 1. ĐẶT VẤN ĐỀ:..……………………………………………………2
1. Lý do chọn đề tài: ………………………………………………...…2
2. Tính cấp thiết của đề tài: ……………………………………………3
3. Tính mới của đề tài: ………………………………………………...3
4. Khả năng ứng dụng và triển khai đề tài: ………………………… ..3
5. Đối tượng và phạm vi nghiên cứu: …………………………………3
PHẦN 2. NỘI DUNG NGHIÊN CỨU ……………..………………………..3
1. Cơ sở khoa học: ……………………………………………………..4
2. Thực trạng của vấn đề: ……………………………………………...4
3. Phương hướng và giải quyết : ……………………………………….5
3.1. Một số định hướng để viết code cho các bài toán xử lý chuổi:…….5
3.2. Vận dụng định hướng để giải một số bài toán kiểu chuổi:………..13
4. Khảo sát sự cấp thiết và tính khả thi của giải pháp:……..…………..26
PHẦN 3. KẾT LUẬN VÀ KHUYẾN NGHỊ: ……………… …………… . 28
TÀI LIỆU THAM KHẢO: ……………………………………………. …29

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chun ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thông tin document, khoa luan, tieu luan, 123


4 of 98.


2
PHẦN I. ĐẶT VẤN ĐỀ
1. Lý do chọn đề tài
Chúng ta đang từng bước triển khai Chương trình giáo dục phổ thơng mới,
trong đó mơn Tin học ngày càng khẳng định vai trò chủ đạo trong việc trang bị cho
người học khả năng tìm kiếm, tiếp nhận, mở rộng tri thức và sáng tạo trong thời
đại cách mạng cơng nghiệp lần thứ tư và tồn cầu hóa.
Trong q trình giảng dạy chúng tơi đã dành nhiều thời gian để tìm kiếm,
sưu tầm, phân loại được một số bài tập về xử lý chuổi con. Nên chúng tôi cùng
nghiên cứu và viết đề tài “PHƢƠNG PHÁP GIẢI MỘT SỐ BÀI TỐN
CHUỔI CON BẰNG NNLT C++” nhằm hệ thống hóa toàn bộ kiến thức về dữ
liệu kiểu chuổi để giúp giáo viên và học sinh sử dụng trong việc dạy và học.
Khi trao đổi với đồng nghiệp cùng trường và một số giáo viên ở trường
khác trong khu vực, chúng tơi nhận thấy cịn nhiều giáo viên khi dạy về vấn đề xử
lý chuổi con cịn khó khăn khi đưa ra các bài tập và code viết bằng NNLT C++,
cho nên chúng tôi mạnh dạn trao đổi kinh nghiệm của mình. Rất mong các đồng
nghiệp nhận xét, góp ý để đề tài của chúng tơi ngày càng hồn thiện và ứng dụng
rộng rãi trong thực tiễn.
Các bài toán và code mà chúng tôi đưa ra chỉ nhằm giới thiệu cho học sinh cách
viết chứ chưa hẳn là một phương án tối ưu để giải quyết bài tốn cụ thể đó.
2. Tính cấp thiết của đề tài
Các bài tốn xử lý chuổi con là rất quan trọng trong lập trình, nó thường gây
ra khó khăn cho học sinh khi mới bắt đầu làm quen và Giáo viên khi mới bắt đầu
viết C++. Vì vậy việc đưa ra nhiều bài tốn và code của nó là rất cần thiết.
3. Tính mới của đề tài
- Đưa ra được nhiều bài tập mới về chuổi con và code viết bằng NNLT C++
- Đưa ra một số định hướng để giải bài toán về xử lý chuổi con trong NNLT C++
4. Khả năng ứng dụng và triển khai đề tài
Đề tài có thể là tài liệu tham khảo bổ ích cho Học sinh, Giáo viên THPT đặc
biệt là Học sinh khá, giỏi.

5. Đối tƣợng và phạm vi nghiên cứu
5.1. Đối tƣợng nghiên cứu
- Học sinh THPT.
- Giáo viên trường THPT.

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


5 of 98.

3
- Các bài toán về xử lý chuổi con.
5.2. Phạm vi nghiên cứu
- Bám sát nội dung chương trình Tin học THPT.
- Mở rộng phù hợp với nội dung thi Học sinh giỏi Tỉnh
6. Phƣơng pháp và nhiệm vụ nghiên cứu
6.1. Phƣơng pháp nghiên cứu
- Phương pháp phân tích, tổng hợp.
- Phương pháp thực nghiệm.
6.2. Nhiệm vụ nghiên cứu
Rút ra một số kinh nghiệm để giải các bài toán về xử lý chuổi con khi dạy
tin học lớp 11 chương trình Tin học THPT.
PHẦN II. NỘI DUNG NGHIÊN CỨU
1. Cơ sở khoa học
1.1. Cơ sơ lý luận
Để giải quyết các bài toán về chuỗi con một cách tối ưu, học sinh phải biết khái
niệm về chuỗi con, các thuật tốn thơng dụng; Học sinh phải có kỹ năng nhận dạng
bài toán khi được phát biểu dưới nhiều dạng khác nhau và lựa chọn thuật tốn thích
hợp để giải quyết.
+) Chuỗi là gì?

Trong lập trình, chuỗi là một dãy các ký tự được lưu trữ dưới dạng một mảng các
ký tự. Ví dụ, chuỗi "hello" có thể được lưu trữ trong mảng char s[] = {'h', 'e', 'l', 'l',
'o', '\0'}.
+) Chuỗi con là gì?
Một chuỗi con là một chuỗi mà có thể được tạo ra từ chuỗi ban đầu bằng cách lấy
ra một số ký tự liên tiếp của chuỗi ban đầu. Ví dụ, chuỗi con "ell" được tạo ra từ
chuỗi "hello" bằng cách lấy ra 3 ký tự liên tiếp bắt đầu từ vị trí thứ 1.
+) Thuật tốn tìm chuỗi con
Để tìm chuỗi con trong C++, ta có thể sử dụng các thuật tốn như Vét cạn, Quy
hoạch động, phương pháp phát triển xâu con. Mỗi thuật tốn có cách hoạt động
khác nhau và độ phức tạp thời gian khác nhau, tùy thuộc vào kích thước của chuỗi
ban đầu và chuỗi con cần tìm.
*/ Một số dạng bài toán thƣờng gặp:
Dạng 1: Cho xâu ký tự S. Yêu cầu: Tìm ra tất cả các xâu con của S thoả
mãn điều kiện Q nào đó.
Dạng 2: Cho xâu ký tự S. Yêu cầu: Đưa ra các đoạn ký tự là xâu con của S
thỏa mãn điều kiện Q nào đó. Trong đó điều kiện Q có tính chất: Nếu xâu con A

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


6 of 98.

4
thỏa mãn điều kiện Q thì thì mọi xâu con liên tục của A cũng thoả mãn điều kiện
Q và ta cũng chỉ tính một xâu con là A.
Dạng 3: Cho xâu ký tự S. Yêu cầu: Tìm xâu con dài nhất của S thỏa mãn
điều kiện Q.
Trường hợp 1: Điều kiện Q có tính chất: Xâu con A thỏa mãn điều kiện Q
nhưng các xâu con của A có thể khơng thỏa mãn Q.

Trường hợp 2: Điều kiện Q có tính chất: Nếu xâu con A thỏa mãn điều kiện
Q thì mọi xâu con liên tục của A cũng thoả mãn tính chất Q và các ký tự của A
không được xét vào xâu con khác.
1.2. Cơ sơ thực tiễn
Chúng tơi đã tìm tịi các bài tốn về chuổi con, nghiên cứu kỹ các code và
đúc rút ra một số kinh nghiệm cho bản thân trong quá trình dạy học.

2. Thực trạng
Các bài tốn về xử lý chuổi con là các bài toán cơ bản. Nhưng trong thực tế
vấn đề dạy và học về kiểu chuổi bằng NNLT C++, Giáo viên và Học sinh còn gặp
một số khó khăn và hạn chế

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


7 of 98.

5
3. Phƣơng hƣớng và giải pháp
3.1. Một số định hƣớng để viết code cho các bài toán xử lý chuổi con viết bằng
NNLT C++
Dưới đây là một số định hướng viết code cho các bài toán xử lý chuỗi con bằng
C++:
1. Sử dụng chuỗi đệ quy (Recursion): Đây là phương pháp tiếp cận bài toán
bằng cách sử dụng hàm đệ quy để phân tích chuỗi ban đầu thành các chuỗi
con. Điều này đặc biệt hữu ích trong việc tìm kiếm chuỗi con phù hợp với
một mẫu chuỗi.
2. Sử dụng vòng lặp (Loop): Sử dụng vòng lặp để duyệt qua tất cả các ký tự
trong chuỗi ban đầu và tạo ra các chuỗi con từ ký tự hiện tại đến ký tự cuối
cùng của chuỗi ban đầu. Điều này đặc biệt hữu ích trong việc tìm kiếm chuỗi

con có độ dài cố định.
3. Sử dụng thuật toán động (Dynamic Programming): Đây là một phương pháp
tiếp cận bài toán bằng cách sử dụng bảng để lưu trữ các kết quả phụ thuộc
vào các bài toán con đã được giải quyết trước đó. Điều này đặc biệt hữu ích
trong việc giải quyết các bài tốn có quy mơ lớn.
4. Sử dụng thuật toán KMP (Knuth-Morris-Pratt): Đây là một thuật toán tối ưu
cho việc tìm kiếm chuỗi con phù hợp với một mẫu chuỗi. Thuật toán này sử
dụng một bảng tiền xử lý để lưu trữ thông tin về các tiền tố và hậu tố của
mẫu chuỗi và sử dụng thông tin này để tìm kiếm chuỗi con trong chuỗi ban
đầu.
5. Sử dụng thư viện chuỗi (String Library): C++ cung cấp một số thư viện
chuỗi hữu ích, chẳng hạn như thư viện <string>, cho phép bạn thực hiện các
thao tác chuỗi thông thường, chẳng hạn như tìm kiếm chuỗi con, so sánh
chuỗi và cắt chuỗi. Việc sử dụng thư viện chuỗi có thể giúp tiết kiệm thời
gian
6. Phương pháp phát triển chuỗi con là cách để tách một phần của một chuỗi
ban đầu thành một chuỗi con mới, có độ dài và nội dung khác nhau. Có
nhiều cách để phát triển chuỗi con trong C++, nhưng phương pháp chung là
bạn cần xác định vị trí bắt đầu và độ dài của chuỗi con
3.2. Vận dụng các định hƣớng trên để giải một số bài toán
Giáo viên đưa ra từng dạng bài toán, phân tích đặc điểm bài tốn, ý tưởng
thuật tốn và ví dụ minh họa cho mỗi dạng. Sau đó cho học sinh soạn thảo chương
trình rồi tiến hành chấm bài

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


8 of 98.

6

Dạng 1: Bài toán duyệt theo phƣơng pháp vét cạn.
1.1/ Bài tốn:
Cho chuỗi kí tự S. Hãy tìm ra tất cả các chuổi con của S thoả mãn điều kiện
Q.
1.2/ Phân tích:
Với bài tốn này, đề u cầu đưa ra tất cả các chuỗi con (các chuỗi con có
thể lồng nhau, có thể giao nhau) nên phải kiểm tra tất cả các chuỗi con. Để kiểm
tra hết ta phải duyệt theo phương pháp vét cạn.
1.3/ Ý tưởng thuật tốn:
Để giải quyết bài tốn này trong C++, ta có thể sử dụng phương pháp vét
cạn, tức là kiểm tra tất cả các chuỗi con của S có thỏa mãn điều kiện Q hay không.
Cụ thể, ta sẽ duyệt qua tất cả các vị trí i, j (i ≤ j) trong chuỗi S và lấy ra chuỗi con
từ vị trí i đến j. Sau đó, kiểm tra xem chuỗi con này có thỏa mãn điều kiện Q hay
khơng. Nếu có, ta lưu lại đoạn ký tự tìm được và tiếp tục duyệt đến vị trí tiếp theo.
Để kiểm tra chuỗi con có thỏa mãn điều kiện Q hay khơng, ta cần định nghĩa điều
kiện đó. Ví dụ, nếu điều kiện là chuỗi con có chứa chữ số, ta có thể duyệt qua từng
ký tự trong chuỗi con và kiểm tra xem ký tự đó có phải là số hay khơng. Nếu có ít
nhất một ký tự là số, ta coi chuỗi con này thỏa mãn điều kiện Q.
Sau khi duyệt qua tất cả các vị trí trong chuỗi S, ta sẽ có được tất cả các đoạn ký tự
thỏa mãn điều kiện Q. Ta in ra các đoạn này và kết thúc chương trình.

Dưới đây là code về cách giải bài toán này trong C++
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
getline(cin, s); // nhập xâu ký tự


for (int i = 0; i < s.length(); i++)

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


9 of 98.

7
{
for (int j = i; j < s.length(); j++)
{
string sub = s.substr(i, j - i + 1); // lấy xâu con từ vị trí i đến j
// kiểm tra xâu con có thỏa mãn điều kiện Q hay không
if (/*Điều kiện Q*/)
{
cout << i << " " << j << endl; // in ra đoạn ký tự tìm được
}
}
}

return 0;
}
1.4/ Ví dụ:
Xâu ký tự được gọi là đồng nhất khi tất cả các ký tự trong xâu đều giống
nhau.
Cho tệp văn bản Dong_nhat_1.INP gồm 1 dòng chứa xâu ký tự S với độ dài
không quá 250 ký tự. Hãy chỉ ra tất cả các xâu con của xâu S là xâu đồng nhất.
Kết quả ghi vào tệp Dong_nhat_1.OUT mỗi dòng gồm 2 số nguyên cách
nhau một dấu cách là vị trí đầu và cuối xâu con tìm được.
Ví dụ:

Dong_nhat_1.Inp
hooocc

Dong_nhat_1.OUT
11
22
23
24
33

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


10 of 98.

8
34
44
55
56
66
Ý tưởng:
Để giải quyết bài toán này bằng phương pháp vét cạn, chúng ta có thể thực hiện
các bước sau:
1. Đọc chuỗi ký tự S từ tệp đầu vào.
2. Duyệt qua tất cả các xâu con của chuỗi S. Với mỗi xâu con, kiểm tra xem
các ký tự trong xâu con đều giống nhau hay không.
3. Nếu xâu con đồng nhất, ghi lại vị trí đầu và cuối của xâu con vào tệp đầu ra.
4. Kết thúc quá trình duyệt và đóng tệp đầu vào và tệp đầu ra.
Dƣới đây là đoạn code minh họa cho bài toán này:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;
bool checkSame(string s, int start, int end) {
// Hàm kiểm tra xâu con từ vị trí start đến vị trí end có đồng nhất khơng
for(int i = start + 1; i <= end; i++) {
if(s[i] != s[start]) {
return false;
}
}
return true;

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


11 of 98.

9
}

int main() {
ifstream inFile;
ofstream outFile;
inFile.open("Dong_nhat_1.INP");
outFile.open("Dong_nhat_1.OUT");

if(inFile.fail()) {
cout << "Failed to open input file." << endl;

return 0;
}
if(outFile.fail()) {
cout << "Failed to open output file." << endl;
return 0;
}

string s;
inFile >> s;
int len = s.length();

for(int i = 0; i < len; i++) {
for(int j = i; j < len; j++) {
if(checkSame(s, i, j)) {
outFile << i << " " << j << endl;
}

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


12 of 98.

10
}
}

inFile.close();
outFile.close();
return 0;
}

Dạng 2: Bài toán duyệt theo phƣơng pháp phát triển chuổi con.
2.1/ Bài toán:
Cho chuổi S. Hãy đưa ra các đoạn ký tự là chuổi con của S thỏa mãn điều
kiện Q nào đó. Trong đó điều kiện Q có tính chất: Nếu chuổi con A thỏa mãn điều
kiện Q thì mọi chuổi con liên tục của A cũng thoả mãn tính chất Q và lúc đó ta
cũng chỉ tính một chuổi con là A.
2.2/ Phân tích:
Với dạng này yêu cầu chuổi con thoả mãn Q có các tính chất trên nên ta sẽ
duyệt theo phương pháp Phát triển chuổi con (kiểm tra sự thỏa mãn của phần tử
tiếp theo để bổ sung vào đoạn đã tìm được).
2.3/ Ý tưởng thuật toán:
Đầu tiên, ta khởi tạo một chuỗi rỗng, sau đó duyệt qua từng ký tự của chuỗi
S. Tại mỗi bước lặp, ta thêm ký tự đó vào cuối chuỗi rỗng để tạo thành một chuỗi
con mới. Sau đó, ta kiểm tra xem chuỗi con mới này có thỏa mãn điều kiện Q hay
khơng. Nếu thỏa mãn, ta lưu trữ chuỗi con này vào một danh sách các chuỗi con
thỏa mãn Q.
Sau khi duyệt qua toàn bộ chuỗi S, ta sẽ có danh sách các chuỗi con của chuỗi S
thỏa mãn điều kiện Q.
Ví dụ, nếu điều kiện Q là "chuỗi con chứa ít nhất một ký tự 'a'",
Code minh họa nhƣ sau
#include <iostream>
#include <string>
#include <vector>
using namespace std;

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


13 of 98.


11
int main()
{
string s = "abcbadefga";
vector<string> substrings;
string sub = "";
for(int i = 0; i < s.length(); i++)
{
sub += s[i];
if(sub.find('a') != string::npos)
{
substrings.push_back(sub);
}
}

cout << "Substrings that contain 'a': ";
for(int i = 0; i < substrings.size(); i++)
{
cout << substrings[i] << " ";
}
cout << endl;

return 0;
}
2.4/ Ví dụ:
Xâu ký tự được gọi là đồng nhất khi tất cả các ký tự trong xâu đều giống
nhau.

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thông tin document, khoa luan, tieu luan, 123



14 of 98.

12
Cho tệp văn bản DONG_NHAT_2.INP gồm 1 dòng chứa xâu ký tự S với độ
dài không quá 250 ký tự. Hãy cắt xâu S thành các xâu con đồng nhất, sao cho số
xâu con là ít nhất. Kết quả ghi vào tệp DONG_NHAT_2.Out mỗi dòng là 1 xâu
con đồng nhất.
Dong_nhat_2.Inp
hooocc

Dong_nhat_2.OUT
h
ooo
cc

Ý tưởng:
Đầu tiên, ta duyệt qua từng ký tự của chuỗi S. Tại mỗi bước lặp, ta kiểm tra xem
ký tự hiện tại có giống với ký tự trước đó hay khơng. Nếu giống nhau, ta thêm ký
tự đó vào chuỗi con hiện tại. Nếu khác nhau, ta lưu trữ chuỗi con hiện tại vào danh
sách các chuỗi con đồng nhất và khởi tạo chuỗi con mới bắt đầu từ ký tự hiện tại.
Sau khi duyệt qua toàn bộ chuỗi S, ta sẽ có danh sách các chuỗi con đồng nhất của
chuỗi S.
Code bài toán:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()

{
ifstream infile("DONG_NHAT_2.INP");
ofstream outfile("DONG_NHAT_2.OUT");
string s;
getline(infile, s);
vector<string> substrings;

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


15 of 98.

13
string sub = "";
for(int i = 0; i < s.length(); i++)
{
if(sub == "" || s[i] == sub[0])
{
sub += s[i];
}
else
{
substrings.push_back(sub);
sub = "";
sub += s[i];
}
}

substrings.push_back(sub); // lưu trữ chuỗi con cuối cùng
for(int i = 0; i < substrings.size(); i++)

{
outfile << substrings[i] << endl;
}

infile.close();
outfile.close();
return 0;
}

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


16 of 98.

14
Dạng 3: Bài tốn tìm xâu con dài nhất.
3.1/ Bài tốn:
Cho chuỗi ký tự S. Tìm ra chuỗi con dài nhất thoả mãn một tính chất Q nào
đó.
3.2/ Phân tích:
Bài tốn trên có thể giải quyết bằng một số phương pháp như:
1. Vét cạn: Kiểm tra tất cả các chuỗi con của chuỗi S và kiểm tra tính chất Q
của từng chuỗi con. Lưu lại độ dài của chuỗi con thoả mãn tính chất Q và trả
về chuỗi con dài nhất.
2. Sử dụng thuật toán Quy hoạch động: Dùng một mảng dp để lưu độ dài của
chuỗi con dài nhất thoả mãn tính chất Q tại mỗi vị trí trong chuỗi S. Từ đó,
ta có thể tính tốn độ dài của chuỗi con dài nhất thoả mãn tính chất Q tại vị
trí cuối cùng của chuỗi S.
3. Sử dụng phương pháp phát triển chuổi con.
3.3/ Ý tưởng giải bài toán trên bằng phương pháp phát triển chuổi con

1. Tạo ra tất cả các chuỗi con có thể từ chuỗi S.
2. Kiểm tra tính chất Q của từng chuỗi con.
3. Lưu lại độ dài của chuỗi con thoả mãn tính chất Q và trả về chuỗi con dài
nhất.
Ta có thể cài đặt đoạn code nhƣ sau:
#include <iostream>
#include <string>
using namespace std;
// Hàm kiểm tra tính chất Q của một chuỗi con
bool check(string str) {
// Code kiểm tra tính chất Q của chuỗi con ở đây
}
// Hàm tìm chuỗi con dài nhất thoả mãn tính chất Q
string longestSubstring(string s) {

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


17 of 98.

15
string result = ""; // Chuỗi con dài nhất thoả mãn tính chất Q
int n = s.length();
// Phát triển các chuỗi con và kiểm tra tính chất Q của chúng
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
string sub = s.substr(i, j-i+1); // Tạo chuỗi con từ vị trí i đến j
if (check(sub) && sub.length() > result.length()) { // Nếu chuỗi con
thoả mãn tính chất Q và dài hơn chuỗi con hiện tại
result = sub; // Lưu lại chuỗi con mới

}
}
}
return result;
}
// Hàm main để kiểm tra
int main() {
string s;
cin >> s;
string result = longestSubstring(s);
cout << result << endl;
return 0;
}
3.4/ Ví dụ:
Bài tốn: CHUỖI ĐỒNG NHẤT
Chuỗi ký tự được gọi là đồng nhất khi tất cả các ký tự trong chuỗi đều giống
nhau.
Cho tệp văn bản Dong_nhat_3.INP gồm 1 dịng chứa chuỗi ký tự S với độ
dài khơng quá 104 ký tự. Hãy đưa ra chuỗi con đồng nhất có độ dài lớn nhất của

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


18 of 98.

16
chuỗi S. Nếu có nhiều chuỗi con thỏa mãn thì đưa ra dãy đầu tiên tính từ trái sang
phải.
Kết quả ghi vào tệp Dong_nhat_3.OUT gồm 1 dòng là chuỗi con tìm được.
Ví dụ:

Dong_nhat_3.Inp
hooocc

Dong_nhat_3.OUT
ooo

Ý tưởng:


Duyệt từ đầu đến cuối chuỗi S và lưu trữ số lượng ký tự đồng nhất liên tiếp
tại mỗi vị trí. Ví dụ, nếu chuỗi S là "abbbccdd", ta sẽ có mảng count = {1, 3,
2, 2, 1, 1, 1, 1}.



Duyệt qua mảng count và tìm phần tử lớn nhất. Lưu lại vị trí của phần tử lớn
nhất đó.



Sử dụng vị trí lớn nhất đã tìm được và độ dài phần tử lớn nhất đó để trích
xuất chuỗi con đồng nhất có độ dài lớn nhất từ chuỗi S.

Code của bài toán:
#include <iostream>
#include <string>
using namespace std;
int main() {
string S;
cin >> S;

int n = S.length();
int count[n];
for (int i = 0; i < n; i++) {
int j = i + 1;
while (j < n && S[j] == S[i]) j++;
count[i] = j - i;
}
int max_len = 0, max_pos = 0;
for (int i = 0; i < n; i++) {
if (count[i] > max_len) {

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


19 of 98.

17
max_len = count[i];
max_pos = i;
}
}
string result = S.substr(max_pos, max_len);
cout << result << endl;
return 0;
}
3.4 – BÀI TẬP ÁP DỤNG:
Để học sinh có năng lực phân tích, vận dụng các phương pháp. Học sinh
cùng giáo viên giải một số bài tập.
1/ Giải một số đề thi HSG Tỉnh Nghệ An:
Bài 1. RÚT GỌN XÂU (Đề thi HSG tỉnh lớp 12 năm học 2009 – 2010)

Cho một xâu S chỉ gồm các chữ cái in thường với độ dài tối đa 250 ký tự.
Em hãy viết chương trình để tạo ra xâu SG từ xâu S bằng cách xóa các ký tự liên
tiếp giống nhau trong xâu S và chỉ để lại một kí tự đại diện trong đoạn đó.
Dữ liệu vào: Đọc từ file văn bản XAUGON.INP chứa xâu S chỉ gồm các chữ cái
in thường.
Kết quả: Ghi ra file văn bản XAUGON.OUT là xâu SG tìm được.
Ví dụ:
XAUGON.INP
Hhooocccsssiiiiinnnhhh

XAUGON.OUT
hocsinh

Phân tích bài tốn:
Với bài tốn này ta có thể hiểu: Xâu SG là kết quả của việc nối ký tự đầu
tiên của các xâu con đồng nhất trong xâu S. Vì vậy ta có thể duyệt theo phương
pháp phát triển xâu con để xác định ký tự đầu dãy con.
Code bài tốn:
#include <iostream>
#include <fstream>

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


20 of 98.

18
#include <string>
using namespace std;
int main() {

ifstream fin("XAUGON.INP");
ofstream fout("XAUGON.OUT");
string S, SG;
fin >> S;
char prev_char = '\0';
for (char c : S) {
if (c != prev_char) {
SG += c;
prev_char = c;
}
}
fout << SG << endl;
fin.close();
fout.close();
return 0;
}

Bài 2: NÉN XÂU (Đề thi HSG tỉnh lớp 12 năm học 2011 – 2012)
Một xâu ký tự có thể nén lại bằng 1 xâu mới bằng cách nén các ký tự giống
nhau đứng cạnh nhau. Ví dụ trong xâu AAAA sẽ nén thành 4A. Hãy lập trình để
nén 1 xâu ký tự in hoa theo cách trên.

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thông tin document, khoa luan, tieu luan, 123


21 of 98.

19
Dữ liệu: Vào từ file văn bản NENXAU.INP một xâu, mà các ký tự là chữ cái in
hoa.

Kết quả: Ghi vào xâu văn bản NENXAU.OUT một xâu ký tự sau khi nén.
Ví dụ:
NENXAU.INP

NENXAU.OUT

MMAABBBEEEEZH

2M2A3B4EZH

Phân tích bài tốn:
u cầu bài tốn chính là xác định độ dài và ký tự của các xâu con đồng
nhất. Kết quả ghi vào tệp nên ta không cần sử dụng xâu phụ để lưu kết quả mà ghi
trực tiếp sau mỗi xâu con tìm được. Sử dụng phương pháp phát triển xâu con ta
có chương trình như sau.
Code bài tốn
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream inFile("NENXAU.INP");
ofstream outFile("NENXAU.OUT");
string inputStr;
getline(inFile, inputStr);
string compressedStr;
char currentChar = inputStr[0];
int count = 1;
for (int i = 1; i < inputStr.length(); i++) {
if (inputStr[i] == currentChar) {

count++;
} else {

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


22 of 98.

20
if (count == 1) {
compressedStr += currentChar;
} else {
compressedStr += to_string(count) + currentChar;
}
currentChar = inputStr[i];
count = 1;
}
}
if (count == 1) {
compressedStr += currentChar;
} else {
compressedStr += to_string(count) + currentChar;
}
outFile << compressedStr;
inFile.close();
outFile.close();
return 0;
}
Bài 3. XÂU CON CHUNG DÀI NHẤT
(Đề thi HSG tỉnh lớp 12 năm học 2012 – 2013)

Xâu S được gọi là xâu con chung của xâu S1 và xâu S2 nếu xâu S là một dãy
các ký tự liên tiếp trong S1 và cũng là dãy các ký tự liên tiếp trong S2.
Yêu cầu: Cho hai xâu kí tự S1 và S2 (có khơng q 255 ký tự). Hãy tìm một xâu
con chung S dài nhất của hai xâu S1 và S2. Ví dụ: S1 = ’Ky thi học sinh gioi Tinh
môn Tin hoc’, S2 = ’hoc sinh gioi mon Tin hoc’ thì S = ‘hoc sinh gioi '.
Dữ liệu vào từ file văn bản Bai2.inp:

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


23 of 98.

21
 Dòng đầu tiên ghi xâu S1;
 Dòng thứ hai ghi xâu S2.
Kết quả ghi ra file văn bản Bai2.out: Chỉ một số duy nhất là độ dài của xâu con
chung dài nhất S. (Nếu hai xâu S1, S2 khơng có kí tự nào chung thì ghi số 0).
Ví dụ:
Bai2.inp
Ky thi hoc sinh gioi Tinh mon tin hoc

Bai2.inp
14

hoc sinh gioi mon Tin hoc
Phân tích bài tốn:
Đây là bài tốn tìm chuỗi con dài nhất của một chuỗi trong chuỗi cịn lại. Ta
có thể sử dụng quy hoạch động.
Cụ thể, ta có thể tạo một ma trận dp với kích thước (m+1)x(n+1) (m, n là độ dài
của hai xâu S1 và S2), trong đó phần tử dp[i][j] sẽ lưu trữ độ dài của xâu con

chung dài nhất của đoạn S1[1...i] và đoạn S2[1...j]. Vậy nếu kí tự thứ i trong S1 và
kí tự thứ j trong S2 giống nhau, thì ta có dp[i][j] = dp[i-1][j-1] + 1, ngược lại thì ta
có dp[i][j] = max(dp[i-1][j], dp[i][j-1]).
Kết quả cần tìm sẽ nằm ở ơ dp[m][n] của ma trận.
Code bài tốn:
#include <iostream>
#include <cstring>
using namespace std;
const int MAX = 255;
int dp[MAX][MAX];
int LCS(string s1, string s2) {
int m = s1.length();
int n = s2.length();
memset(dp, 0, sizeof(dp)); // Khởi tạo ma trận dp ban đầu

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Cơng ngh thơng tin document, khoa luan, tieu luan, 123


24 of 98.

22
// Xây dựng ma trận dp
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}

}
return dp[m][n];
}
int main() {
string s1, s2;
getline(cin, s1); // Nhập xâu S1
getline(cin, s2); // Nhập xâu S2
int res = LCS(s1, s2);
cout << res << endl; // Xuất kết quả
return 0;
}
Bài 6. XÂU CON (Đề thi HSG tỉnh lớp 11 năm học 2014 – 2015)

Cho trước một xâu có độ dài L (1 < L < 2.105) chỉ chứa các chữ cái thường
trong bảng chữ cái tiếng Anh.
Yêu cầu:
Hãy tìm xâu con dài nhất xuất hiện ít nhất 2 lần trong xâu đã cho.
Dữ liệu vào từ file XAU.INP:

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


25 of 98.

23
Dòng đầu là một số nguyên L.
Dòng sau là một xâu có độ dài L.
Kết quả ghi ra file XAU.OUT: Chỉ một số duy nhất là độ dài của xâu con
tìm được, nếu khơng tìm được thì ghi ra 0.
Ví dụ:

XAU.INP

11

XAU.OUT

3

sabcabcfabc

XAU.INP

XAU.OUT

4
18
trutrutiktiktappop

XAU.INP

6
abcdef

XAU.OUT

0

Phân tích bài tốn:
Để giải quyết bài tốn này, ta có thể sử dụng thuật tốn KMP để tìm kiếm chuỗi
con xuất hiện ít nhất 2 lần trong xâu đã cho.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<int> prefixFunction(string s) {
int n = s.length();
vector<int> pi(n, 0);
for (int i = 1; i < n; i++) {
int j = pi[i-1];
while (j > 0 && s[i] != s[j]) {
j = pi[j-1];
}
if (s[i] == s[j]) {
j++;
}
pi[i] = j;
}

Tng hp các án, khóa lun, tiu lun, chuyên và lun vn tt nghip i hc v các chuyên ngành: Kinh t, Tài Chính & Ngân Hàng, Công ngh thông tin document, khoa luan, tieu luan, 123


×