SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ TRƯỜNG THPT VĨNH LỘC SÁNG KIẾN KINH NGHIỆM MỘT SỐ KINH NGHIỆM BỒI DƯỠNG HỌC SINH GIỎI VỀ KIỂU DỮ LIỆU XÂU... Qua hai năm bồi dưỡng học sinh giỏi cấp tỉnh
Trang 1SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ
TRƯỜNG THPT VĨNH LỘC
SÁNG KIẾN KINH NGHIỆM
MỘT SỐ KINH NGHIỆM BỒI DƯỠNG HỌC SINH GIỎI VỀ KIỂU DỮ LIỆU XÂU
Trang 2THANH HOÁ NĂM 2021
Trang 32 Nội dung sáng kiến kinh nghiệm 22.1 Cơ sở lý luận của sáng kiến kinh nghiệm 22.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm 22.3 Các giải pháp đã sử dụng để giải quyết vấn đề 2
2.3.2 Các dạng bài tập thường gặp 42.3.3 Một số bài tập áp dụng 132.4 Hiệu quả của sáng kiến kinh nghiệm đối với hoạt động giáo dục,
với bản thân, đồng nghiệp và nhà trường 16
Trang 51 Mở đầu
1.1 Lý do chọn đề tài
Trong thời kỳ hội nhập, Công nghệ thông tin là một trong những ngànhmũi nhọn mang đến sự phát triển vượt bậc cho khoa học kỹ thuật Chính vì vậy,ngành công nghệ thông tin đã trở thành một ngành học “hot” và thu hút rất nhiềubạn học sinh sắp tốt nghiệp trung học phổ thông, đặc biệt là những bạn yêu thíchmáy tính và đam mê công nghệ Tuy nhiên một thực tế tại các trường trung họcphổ thông thì môn Tin học đang được đa số các học sinh xem là “môn phụ” vàdành rất ít sự quan tâm cho môn học này Vì vậy để góp phần khẳng định vai tròcủa môn Tin học trong trường so với các môn học khác và tạo điểm nhấn kíchthích sự quan tâm, hứng thú của học sinh với môn Tin thì việc nâng cao chấtlượng đội tuyển học sinh giỏi là một nhiệm vụ trọng tâm
Trên thực tế, ngoại trừ các trường chuyên thì ở các trường trung học phổthông khác ngôn ngữ đang được sử dụng chủ yếu để dạy cho đội tuyển học sinhgiỏi tin học là ngôn ngữ Pascal Tuy nhiên hiện nay trong các kỳ thi học sinhgiỏi Tỉnh thì ngôn ngữ C++ là ngôn ngữ đang được sử dụng thay thế dần ngônngữ lập trình Pascal Vì vậy để các em học sinh trong đội tuyển học sinh giỏiTin học của nhà trường tiếp cận ngôn ngữ lập trình C++ là một vấn đề rất cấpthiết Đây cũng là một thuận lợi cho các em có định hướng học ngành công nghệthông tin ở bậc đại học vì vậy sẽ dễ tạo hứng thú học tập cho các em hơn
Qua hai năm bồi dưỡng học sinh giỏi cấp tỉnh bằng việc cho học sinh sửdụng ngôn ngữ lập trình C++, tôi nhận thấy dữ liệu kiểu xâu thường gặp phổbiến trong các bài toán và việc vận dụng linh hoạt các thao tác xử lí kiểu dữ liệunày vào giải quyết các bài toán liên quan không phải dễ Bên cạnh đó tài liệutham khảo phổ thông chính thống về ngôn ngữ lập trình C++ còn khá hạn chế
Vì vậy, với mong muốn phần nào giúp học sinh cũng như giáo viên trong việctìm ra lời giải cho một số bài toán liên quan tới kiểu dữ liệu xâu dễ dàng hơn, tôi
chọn đề tài “MỘT SỐ KINH NGHIỆM BỒI DƯỠNG HỌC SINH GIỎI VỀ KIỂU DỮ LIỆU XÂU TRONG NGÔN NGỮ LẬP TRÌNH C++” làm đề tài
sáng kiến kinh nghiệm của mình
1.2 Mục đích nghiên cứu
- Giới thiệu một số thao tác xử lí xâu cơ bản trong c++
- Hệ thống một số dạng bài tập thường gặp giúp học sinh và giáo viên phầnnào nhận dạng được một số bài tập liên quan
1.3 Đối tượng nghiên cứu
- Các bài toán liên quan đến kiểu dữ kiệu xâu
1.4 Phương pháp nghiên cứu
- Khảo sát, phân tích, giải quyết vấn đề kết hợp giữa lí thuyết và thực hành
- Kết hợp thực tiễn dạy đội tuyển học sinh giỏi ở trường trung học phổ thôngVĩnh Lộc
- Tham khảo các tài liệu về ngôn ngữ lập trình C++ và tài liệu về sáng kiến
- Tham khảo ý kiến góp ý của đồng nghiệp
Trang 62 Nội dung sáng kiến kinh nghiệm
2.1 Cơ sở lí luận của sáng kiến kinh nghiệm
Trong điều kiện hướng tới thực hiện chương trình GDPT mới (2018),trước tình hình thực tế Bộ giáo dục và đào tạo đã ban hành công văn3280/BGDDT-GDTrH, kèm theo hướng dẫn điều chỉnh nội dung dạy học cấptrung học phổ thông năm 2020 Đối với việc giảng dạy nội dung về ngôn ngữlập trình của môn Tin học lớp 11, Bộ có một số lưu ý cụ thể là “Hiện nay cónhiều ngôn ngữ lập trình có tính cập nhật, hiện đại, đồng thời thông dụng tronggiáo dục phổ thông ở nhiều nước mà các trường có thể lựa chọn như Python, C,C++, “
Trong ngôn ngữ lập trình C++, kiểu dữ liệu xâu thường có hai loại vớithao tác được sử dụng với hai loại này là khác nhau Vấn đề quan trọng là tùythuộc vào yêu cầu của mỗi bài toán cụ thể, làm thế nào để học sinh phân loạiđược dạng toán và sử dụng kiểu dữ liệu phù hợp, thuận lợi cho quá trình lậptrình
2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm
Qua thực tế dạy bồi dưỡng đội tuyển học sinh giỏi, tôi nhận thấy trong đềthi học sinh giỏi tỉnh qua các năm ở các địa phương hầu hết đều có bài toán liênquan đến kiểu dữ liệu xâu Bên cạnh đó khi bắt tay vào giải quyết bài toán họcsinh thường gặp khó khăn khi sử dụng các thao tác cơ bản với kiểu dữ liệu này
và cũng khá nhiều lần nhầm lẫn giữa thao tác của kiểu xâu theo phong cách C vàkiểu xâu theo phong cách C++
2.3 Các giải pháp đã sử dụng để giải quyết vấn đề
2.3.1 Kiểu xâu trong C++
Trong C++ có hai loại xâu, xâu theo phong cách của C (C – style string)
và xâu theo phong cách của C++ (C++ - style string)
C - Style string thực sự là một mảng các ký tự, nhưng có một số hàm khácnhau được sử dụng cho các xâu, ví dụ như thêm vào các xâu, tìm chiều dài củaxâu, và các hàm kiểm tra phù hợp của string với một biểu thức chính quy(regular expression)
C++ - Style string thực chất là một mảng các ký tự, nhưng sử dụng dấunháy kép để dánh dấu một xâu kí tự (string literals)
Trang 7char *strcpy(char *dest,
const char *src)
Sao chép xâu 'src' sang cho 'dest'
int strcmp(const char *str1,
const char *str2)
So sánh hai string cho bởi tham số con trỏstr1, và str2 Nó trả về một số nguyên > 0nghĩa là str1 > str2 Và = 0 nghĩa là 2 xâugiống nhau, ngược lại str1 < str2
char *strcat(char *st1, const
char *st2)
Nối xâu st2 vào cuối xâu st1
char *strchr(const char *str,
int c)
Vị trí xuất hiện đầu tiên của xâu str trong xâustrchr bắt đầu từ vị trí c
int atoi(const char * str); Chuyển đổi xâu thành số nguyên
Itoa(int n, char *st, cơ số) Chuyển đổi số nguyên thành xâu
2.3.1.2 C++ - style string
2.3.1.2.1 Khai báo
String st; // khai báo xâu st
2.3.1.2.2 Khởi tạo hoặc gán giá trị
Có thể khởi tạo hoặc gán giá trị cho biến string theo nhiều cách:
string st(""); // Khởi tạo xâu st rỗng
string st1("Hello"); // Khởi tạo xâu "Hello" cho st1
string st2 = "hello word"; // Khởi tạo xâu "Hello A1" cho st2
string st= "88"; // Khởi tạo xâu "88" cho st, không phải số
st.length() Độ dài của xâu st
st=st1+st2; Nối xâu st2 vào cuối xâu st1
Trang 8st.at(vt); Lấy kí tự ở vị trí vt của xâu st
st1<toán tử so sánh>st2 So sánh hai xâu st1 và st2
St.find(s) Trả về vị trí đầu tiên khi tìm thấy xâu s trong xâu
stSt.find(s,x) Trả về vị trí đầu tiên khi tìm thấy xâu s trong xâu
st bắt đầu từ vị trí xst.erase(x, y); Xóa đi y kí tự trong xâu st bắt đầu từ vị trí x
st.substr(x,y) Trả về xâu con từ vị trí thứ x đến y trong xâu st
2.3.2 Các dạng bài tập thường gặp
2.3.2.1 Xử lí số nguyên lớn
Phương pháp chung: Để thực hiện các phép tính hoặc xử lý với số
nguyên ngoài phạm vi biểu diễn được cung cấp, cách đơn giản nhất là sử dụngxâu kí tự để biểu diễn với mỗi ký tự của xâu tương ứng với một chữ số của sốnguyên lớn tính từ trái qua phải
Bài 1: Cộng hai số nguyên lớn
Cho hai số nguyên dương lớn có có độ dài không quá 200 chữ số Hãy đưa
Bước 2: Duyệt lần lượt từ cuối hai xâu về đầu:
- Tách từng phần tử của hai xâu chuyển sang kiểu số.
- Tính tổng:
Tổng= số 1 + số 2 + nhớ ( ban đầu nhớ =0) Nhớ=tổng/10
Tong =tong % 10;
- Chuyển đổi tổng tính được sang dạng sô rồi cộng vào xâu kết quả.
- Lưu ý cộng thêm giá trị nhớ lần cuối nếu gia trị nhớ khác 0.
Đoạn chương trình tính tổng hai số nguyên lớn
String congxau(string a, string b)
Trang 9- Duyệt từ cuối xâu lớn về đầu xâu.
- - Tách từng phần tử của xâu chuyển sang kiểu số và tính tích.
Tich=số nhỏ*tg-nhớ (tg là số được tách từ xâu lớn)
Nhớ=tich/10;
Tich=tich%10
- Chuyển đổi giá trị tích tính được sang kí tự rồi gán cho xâu kết quả.
- Lưu ý cộng thêm giá trị nhớ lần cuối nếu nhớ khác ‘0’.
Đoạn chương trình tham khảo
String nhan1so(string a, int k)
Bài 3: Nhân hai số nguyên lớn
Cho hai số nguyên dương lớn a, b có có độ dài không quá 200 chữ số Hãyđưa ra tích của 2 số nguyên đó
Ý tưởng:
- Duyệt từ cuối xâu s về đầu xâu.
- Tách từng phần tử của xâu a nhân với xâu b.
- Cộng liên tiếp các kết quả thu được (lưu ý trước khi cộng 2 xâu thêm
kí tự ‘0’ vào cuối xâu thứ hai)
- Xử lí các kí tự ’0’ trước xâu sau khi cộng.
2.3.2.2 Biến đổi xâu
Trang 10Phương pháp chung: Đây là dạng cơ bản thường gặp, việc biến đổi xâu
được thực hiện trên mỗi ký tự trong xâu nên cần nắm rõ các thao tác trên kiểu
dữ liệu xâu để vận dụng một cách linh hoạt vào từng bài tập cụ thể
Bài 1: Tìm số lớn
Cho một dãy gồm N các kí tự có mặt trên bàn phím trong đó có ít nhất 4chữ số (N<106)
Yêu cầu: Hãy loại bỏ một số kí tự cuối dãy sao cho 4 kí tự cuối cùng còn lại
theo đúng thứ tự đó tạo nên số lớn hất
Dữ liệu vào: file văn bản BAI2.INP chứa N kí tự.ư
Kết quả ra: file văn bản BAI2.OUT chứa 4 chữ số tạo thành số lớn nhất.
Ví dụ:
BAI1.INP BAI1.OUT
2124t5j4r05f704y652k393 7693
Ý tưởng:
- Xóa các kí tự không phải là kí tự chữ số xuất hiện trong xâu.
- Thực hiện tìm lần lượt các chữ số lớn nhất ở 4 vị trí từ trái qua phải.
Ví dụ chữ số lớn nhất mà kí tự chữ số lớn nhất từ đầu xâu đến vị trí s.length()-4,
Chương trình tham khảo
for (int i=0; i<s.length(); i++)
if (s[i]!='0' && s[i]!='1' && s[i]!='2' && s[i]!='3' && s[i]!='4' && s[i]!='5' && s[i]!='6' && s[i]!='7' && s[i]!='8' && s[i]!='9')
{
s.erase(i,1);
i ;
} y<<s<<endl;
for (k=4;k>=1;k )
{if (s.length()==k) {s1=s1+s; break;}
max[0]=s[0];int n=s.length();
for (i=1;i<=n-k;i++)
Trang 11x.close(); y.close();
return 0;}
Bài 2: TỪ VỰNG [1]
Muốn cải thiện vốn từ vựng tiếng Anh của mình thông qua trò chơi nhận
diện từ, Quyên tự viết ra một xâu S độ dài không quá 106 chỉ gồm các kí tựthường trong bảng chữ cái tiếng Anh Từ đó, Quyên tìm ra tất cả từ vựng có
trong S Một từ vựng sẽ thu được bằng cách ghép một số kí tự liên tiếp lấy từ S,
giữ nguyên trật tự của chúng, thỏa mãn một trong hai điều kiện sau:
Bắt đầu bằng một nguyên âm (là các chữ cái: a, e, i, o, u) và kết thúc bằng
một phụ âm (là các chữ cái còn lại)
Bắt đầu bằng một phụ âm và kết thúc bằng một nguyên âm
Yêu cầu: Hãy giúp bạn Quyên đếm số lượng từ vựng có trong S theo quy tắc
trên
Dữ liệu: Vào từ tệp CAU4.INP gồm xâu S không quá 106 kí tự
Kết quả: Ghi ra tệp CAU4.OUT một số nguyên là kết quả tìm được.
Ví dụ:
Ràng buộc:
- Có ⅔ số test còn lại không có rằng buộc gì thêm.
Ý tưởng
- Duyệt lần lượt từng kí tự trong xâu, lưu số lượng kí tự nguyên âm và phụ
âm đến thời điểm hiện tại đang xét.
- Nếu kí tự đang xét là một nguyên âm thì số lượng từ vựng bằng số lượng
từ vựng trước đó cộng vơi số lượng phụ âm, đồng thời tăng số lượng nguyên âm lên 1 đơn vị.
- Nếu kí tự đang xét là một phụ âm thì số lượng từ vựng bằng số lượng từ vựng trước đó cộng vơi số lượng nguyên âm, đồng thời tăng số lượng phụ
âm lên 1 đơn vị.
Chương trình tham khảo
Trang 12return (ch=='a'||ch=='e'||ch=='i'||ch=='o' ||ch=='u');
}
const char* ff = "CAU4.INP";
const char* fo = "CAU4.OUT";
long long pa=0, na=0;
for (int i=0;i<n;i++)
Phương pháp chung: Để tìm các xâu con của xâu ban đều thỏa mãn một
điểu kiện cho trước thì thường sử dụng phương pháp vét cạn với bộ dữ liệu đầuvào nhỏ, tuy nhiên nên sử dụng linh hoạt các phương pháp khác như phươngpháp quy hoạch động trong trường hợp bài toán có bộ dữ liệu lớn
Bài 1: Đếm xâu con [2]
Cho xâu S bao gồm các chữ cái ‘A’ ‘Z’ và các chữ số ‘0’ … ‘9’
Yêu cầu: Đếm số lượng xâu con trong xâu S có số lượng chữ cái nhiều hơn số
lượng chữ số (Xâu con của xâu S là một dãy các kí tự liên tiếp trong xâu S)
Dữ liệu vào: Đọc từ tệp BAI1.INP gồm xâu S có độ dài <=104
Kết quả ra: Ghi ra tệp BAI1.OUT kết quả tìm được.
Trang 13- Gọi b[i] là số lượng chữ số tính từ kí tự đầu tiên đến kí tự thứ i trong xâu S.
- Khi đó đoạn từ kí tự thứ i đến kí tự thứ j trong xâu S có số lượng chữ cái nhiều hơn số lượng chữ số nếu a[j]-a[i]>b[j]-b[i].
- Sử dụng phương pháp vét cạn để tính số xâu con thõa mãn điều kiện đề bài.
Chương trình tham khảo
#include<bits/stdc++.h>
using namespace std;
string s;
int dem=0;long a[10001],b[10001];
const char* ff = "BAI1.INP";
const char* fo = "BAI1.OUT";
for (int i=1;i<s.length();i++)
if (s[i]>=65 && s[i]<=90) a[i]=a[i-1]+1;
else a[i]=a[i-1];
if (s[0]>=48 && s[0]<=57) b[0]=1;
else b[0]=0;
for (int i=1;i<s.length();i++)
if (s[i]>=48 && s[i]<=57) b[i]=b[i-1]+1;
Bài 2 Gửi thư
Vị Giám đốc công ty XYZ cần gửi một văn bản quan trọng tới một đối táccủa mình Văn bản là một xâu S các chữ cái la tinh in thường Để bảo mật nộidung văn bản, ông Giám đốc gửi 2 bức thư Bức thư thứ nhất là phần đầu S1 củaxâu S, bức thư thứ 2 là phần cuối S2 của S Hai bức thư S1 và S2 đảm bảo đầy
đủ nội dung của S, tuy nhiên có thể một phần cuối của S1 có thể được viết lặplại trong phần đầu của S2, song số kí tự được viết lặp lại không biết trước
Yêu cầu: Cho hai xâu Sb và Se, hãy xác định một xâu S có thể là nội dung của
bức thư sao cho độ dài của xâu S là ngắn nhất
Dữ liệu vào: BAI2.INP
Trang 14Dòng đầu chứa xâu S1, dòng thứ hai chứa xâu S2 Mỗi xâu có độ dài <= 250.
Kết quả: BAI2.OUT Ghi ra độ dài của xâu S tìm được.
Ví dụ:
Truong trung học phổ thông
trung học phổ thông Vinh Loc
Truong trung học phổ thôngVinh Loc
Ý tưởng:
- Tìm xâu con chung dài nhất của hai xâu tương ứng tính từ cuối xâu s1
và đầu xâu s2 (giả sử độ dài xâu con chung là max).
- Kết quả bài toán là s1.length() + s2.length()-max
Chương trình
#include<bits/stdc++.h>
using namespace std;
string s1,s2; int k=1;
const char* ff = "BAI3.INP";
const char* fo = "BAI3.OUT";
2.3.2.4 Xâu đối xứng (Palindrome)
Phương pháp chung: Xâu Palindrome hay còn gọi là xâu đối xứng, có
nghĩa một xâu khi đọc các ký tự trong xâu từ trái sang phải cũng giống từ phảisang trái
Với những bài tập kiểm tra xâu Palindrome hay tìm kiếm xâu có tính chấtPalindrome thì trước hết nên xây dựng hàm kiểm tra tính chất đối xứng của mộtxâu với độ phức tạp O(n), trên cơ sở đó chúng ta đi giải quyết những bài tập khóhơn
Bài 1 Xâu Palindrome
Cho một xâu S có độ dài không vượt quá 106 Kiểm tra xem xâu S có phải
là xâu Palindrome hay không?
Trang 15While ( i<=st.length()/2 && st[i] != st[st.length()-1-i]) i++;
If (i>st.length()/2) kt=true; else kt=false;
if kt(s) cout<<”Xau doi xung”
else cout “Xau khong doi xung”;
return 0;
Bài 2 (5 điểm) Từ đối xứng
Bờm là một học sinh rất chuyên cần, hôm nay Bờm đi học sớm, đi đếnlớp thấy 2 bạn đang chơi trò chơi tìm từ đối xứng Nội dung trò chơi là: có mộttrang văn bản, hai bạn sẽ tìm số lượng từ đối xứng nhiều nhất Bờm nghĩ việctìm như hai bạn thì lâu quá nên mình sẽ lập trình để tìm ra đáp số
Từ được phân biệt nhau bởi dấu cách (còn gọi là kí tự cách trống – space).Hai từ được gọi là đối xứng nếu từ đó đọc từ bên trái sang cũng giống nhưkhi đọc từ bên phải sang
Ví dụ: ‘tom’ và ‘mot’ là hai từ đối xứng
Cho tệp văn bản DOIXUNG.INP là một xâu kí tự không quá 105 kí tự baogồm các kí tự từ ‘a’ đến ‘z’ và các kí tự cách trống
In ra tệp DOIXUNG.OUT là số từ đối xứng tương ứng có trong tệpDOIXUNG.INP