SỞ GIÁO DỤC VÀ ĐÀO TẠO NGHỆ AN TRƯỜNG THPT YÊN THÀNH 3 ----------------------------------
SÁNG KIẾN
Đề tài:
RÈN LUYỆN KỸ NĂNG LẬP TRÌNH
VỚI CHỦ ĐỀ XÂU KÝ TỰ CHO HỌC SINH KHÁ GIỎI
TRONG NGÔN NGỮ LẬP TRÌNH C++ VÀ PYTHON
TÁC GIẢ:
ĐIỆN THOẠI:
Tô Thị Tường 0975905669 Toán – Tin
TỔ:
THỜI GIAN THỰC HIỆN: Năm học 2019 - 2020
Năm học 2020 - 2021
----------------------------------
1
Đề tài: “RÈN LUYỆN KỸ NĂNG LẬP TRÌNH VỚI CHỦ ĐỀ XÂU KÝ TỰ
CHO HỌC SINH KHÁ GIỎI
TRONG NGÔN NGỮ LẬP TRÌNH C++ VÀ PYTHON”
MỤC LỤC
NỘI DUNG Trang
3 Phần 1 - ĐẶT VẤN ĐỀ:
I - Lý do chọn đề tài. 3
II – Điểm mới của đề tài. 4
5 Phần 2 - NỘI DUNG.
I – CƠ SỞ LÝ LUẬN 5
1. Vai trò của việc rèn luyện kỹ năng lập trình cho học sinh 5 khá giỏi.
2. Sự cần thiết dạy học cho học sinh khá giỏi về ngôn ngữ lập 5 trình C++ và Python.
3. Tầm quan trọng của chủ đề Xâu ký tự trong dạy học lập 6 trình.
II – THỰC TRẠNG VẤN ĐỀ 6
1. Thực trạng dạy học ngôn ngữ lập trình C++, Python ở các 6 trường THPT.
2. Thực trạng dạy học ngôn ngữ lập trình C++, Python ở 7 trường chúng tôi.
3. Thực trạng dạy học chủ đề xâu dữ liệu cho đối tượng học 7 sinh khá giỏi.
III – GIẢI QUYẾT VẤN ĐỀ 8
8 1 – Một số đặc tính và kiến thức cơ bản về xâu dữ liệu trong NNLT C++ và Python
1.1 Một số đặc tính khác nhau giữa Xâu trong C++ và Xâu 8 trong Python
1.2 Tóm tắt một số thao tác xử lý xâu trong C++ 8
2
1.3 Tóm tắt một số thao tác xử lý xâu trong Python 10
11 2 – Rèn luyện kỹ năng lập trình với chủ đề Kiểu xâu
11 2.1 Ôn luyện kỹ năng sử dụng thao tác xử lý xâu qua một số bài toán cơ bản
19 2.2 Rèn luyện kỹ năng giải một số dạng bài tập phổ biến về xâu ký tự.
2.2.1 Dạng bài tập yêu cầu biến đổi xâu 19
2.2.2 Dạng bài tập có yêu cầu duyệt xử lý xâu con 23
2.2.3 Dạng bài tập có yêu cầu xử lý số lớn. 27
31 3 - Một số bài tập mở rộng và nâng cao
42 4 - Hiệu quả của sáng kiến
43 Phần 3. PHẦN KẾT LUẬN
I - Kết luận chung 43
II – Ý nghĩa của đề tài 43
III - Khả năng ứng dụng, mở rộng của đề tài 44
IV - Đề xuất 44
DANH MỤC CÁC CHỮ VIẾT TẮT TRONG SÁNG KIẾN
Nội dung Viết tắt
Giáo dục phổ thông GDPT
Phát triển năng lực. PTNL
Trung học phổ thông THPT
Giáo viên GV
Học sinh HS
Ngôn ngữ lập trình NNLT
Ngôn ngữ lập trình C++ C++
3
Ngôn ngữ lập trình Python Python
Phần 1. ĐẶT VẤN ĐỀ
I. LÝ DO CHỌN ĐỀ TÀI.
Giáo dục phổ thông nước ta đang thực hiện bước chuyển từ chương trình giáo dục tiếp cận nội dung sang chương trình giáo dục “định hướng năng lực”. Trong chương trình giáo dục phổ thông mới, bộ môn Tin học có rất nhiều điểm mới, trong đó Bộ GD-ĐT đã ban hành hướng dẫn điều chỉnh nội dung dạy học, cho phép và khuyến khích các cơ sở giáo dục dần loại bỏ ngôn ngữ lập trình Pascal lựa chọn giảng dạy các ngôn ngữ lập trình có tính cập nhật, hiện đại, và thông dụng như C++, Python…
Hưởng ứng thực hiện nhiệm vụ đổi mới của ngành ở trường chúng tôi đã triển khai dạy học ngôn ngữ lập trình C++ cho toàn bộ học sinh khối 11 thay thế Pascal và trong các hoạt động nhóm chuyên môn chúng tôi đã tổ chức nghiên cứu về ngôn ngữ Python, tổ chức Câu lạc bộ Tin học tập hợp các học sinh yêu thích, đam mê Tin học bước đầu triển khai cho học sinh có sân chơi bổ ích, lành mạnh, thu hút học sinh khá giỏi tham gia học tập, chia sẻ lẫn nhau nhằm khơi dậy niểm đam mê tin học đối với học sinh, đồng thời nâng cao năng lực chuyên môn của giáo viên, trang bị kiến thức, nghiệp vụ sẵn sàng thực hiện tốt nhiệm vụ đổi mới góp phần đi tới đạt mục tiêu chung của ngành.
Là một giáo viên bộ môn Tin học, bên cạch việc dạy học các kiến thức phổ thông về tin học thì việc bồi dưỡng học sinh khá giỏi cũng hết sức quan trọng; trách nhiệm của người giáo viên Tin học là tổ chức các hoạt động học tập cho học sinh để phát triển hệ thống năng lực mà một học sinh phổ thông cần phải có. Khi giảng dạy tôi thường phân tích những điểm ưu, nhược của các ngôn ngữ lập trình để các em có cái nhìn tổng quan, bao quát về một số ngôn ngữ lập trình như C++, Python để gieo niềm đam mê định hướng những học sinh có năng lực vào đội ngũ nhân lực CNTT chất lượng cao của đất nước.
4
Qua quá dạy học, tôi nhận thấy chủ đề “Xâu ký tự” là một nội dung rất quan trọng trong việc tiếp cận ngôn ngữ lập trình bậc cao, xử lý xâu ký tự cũng là yêu cầu thường gặp trong việc xây dựng các phần mềm ứng dụng thực tiễn, nhưng việc dạy học chủ để này ở một số trường THPT còn gặp nhiều khó khăn, hiệu quả chưa cao. Với niềm đam mê chuyên môn, ham học hỏi tôi luôn tìm tòi nghiên cứu và tôi đã có những giải pháp tốt nhất nhằm đem lại hiệu quả cao trong công tác bồi dưỡng học sinh khá giỏi và đã đạt được những kết quả mong đợi. Tôi xin chia sẻ sáng kiến chủ đề “Rèn luyện kỹ năng lập trình với chủ đề xâu ký tự cho học sinh khá giỏi trong ngôn ngữ lập trình C++ và Python” với mong muốn đưa ra được giải pháp nhằm nâng cao hiệu quả bồi dưỡng học sinh khá giỏi và giúp giáo viên có thêm một số cách thức để ôn luyện phù hợp. Qua đó, tôi cũng mong muốn mọi giáo viên Tin học luôn có ý thức tìm tòi, nghiên cứu nâng cao trình độ, năng lực chuyên môn, thực hiện tốt công cuộc đổi mới của ngành.
II. ĐIỂM MỚI CỦA ĐỀ TÀI
- Hiện nay Python là ngôn ngữ lập trình đang được sử dụng rộng rãi để tạo ra các ứng dụng Trí tuệ nhân tạo (AI), phân tích dữ liệu lớn (Big data), học máy (machine learning).... Trong chương trình GDPT mới 2018, python sẽ là một lựa chọn phù hợp để giảng dạy cho học sinh THPT vì câu lệnh đơn giản ngắn gọn, dễ viết, dễ tiếp cận. Với những lý do trên, trường chúng tôi đã triển khai dạy học ngôn ngữ lập trình C++ song song với ngôn ngữ lập trình Python cho học sinh khá giỏi thông qua các số hoạt động học tập như Sinh hoạt Câu lạc bộ Tin học, trong bồi dưỡng học sinh khá giỏi và nghiên cứu khoa học kỹ thuật.
- Sáng kiến này là sự đón đầu giúp giáo viên chuẩn bị kiến thức chuyên môn nghiệp vụ để triển khai chương trình chương trình GDPT 2018 một cách hiệu quả nhất.
- Sáng kiến đã xây dựng các bài toán thành một hệ thống theo một trình tự logic có sự sắp đặt của phương pháp và quy trình giải toán, giúp học sinh dễ dàng tiếp cận với nội dung và rèn luyện tư duy thuật toán .
- Sáng kiến đã chọn lọc hệ thống các bài tập thích hợp, sắp xếp một cách logic, hợp lí từ dễ đến khó nhằm giúp học sinh củng cố kiến thức, rèn luyện kỹ năng phát triển tư duy và biết áp dụng Tin học vào thực tiễn.
5
- Thông qua việc hướng dẫn giải các bài toán giáo viên rèn luyện kỹ năng lựa chọn thuật toán cho học sinh bằng cách định hướng, uốn nắn, trau chuốt từng lời giải từng bài tập, qua đó góp phần tạo niềm tin và hứng thú học tập.
Phần 2. NỘI DUNG
I - CƠ SỞ LÝ LUẬN:
1. Vai trò của việc rèn luyện kỹ năng lập trình cho học sinh khá giỏi.
Trong thời công nghệ 4.0, ngành công nghệ thông tin (CNTT) nói chung và Tin học nói riêng đang phát triển một cách mạnh mẽ. Mọi ngành nghề, lĩnh vực hay hoạt động nào trong xã hội hiện đại cũng cần tới sự góp mặt của CNTT, ở đâu ứng dụng của CNTT cũng vô cùng quan trọng. Vì vậy, nhu cầu về nguồn nhân lực CNTT là rất lớn và vẫn còn tiếp tục tăng vọt trong những năm tiếp theo, việc nâng cao chất lượng nguồn nhân lực CNTT để đáp ứng yêu cầu phát triển và hội nhập kinh tế quốc tế của đất nước là một nhiệm vụ hết sức cấp thiết hiện nay. Là một giáo viên bộ môn Tin học, bên cạch việc dạy học các kiến thức phổ thông về tin học ứng dụng thì việc dạy học lập trình cũng hết sức quan trọng; trách nhiệm của người giáo viên Tin học là giúp học sinh hiểu hơn về sự hoạt động của máy tính, am hiểu về khoa học kỹ thuật, góp phần định hướng những học sinh có năng lực và đam mê Tin học vào đội ngũ nhân lực CNTT chất lượng cao của đất nước.
2. Sự cần thiết dạy học cho học sinh khá giỏi về ngôn ngữ lập trình C++
và Python.
Ngôn ngữ lập trình C++ và Python là ngôn ngữ lập trình phù hợp cho việc dạy học trong trường phổ thông, đều có thể sử dụng trong kỳ thi học sinh giỏi tỉnh Nghệ An vừa qua; đây cũng là hai trong những ngôn ngữ đang được sử dụng phổ biến hiện nay trong việc thiết kế, xây dựng các phần mềm ứng dụng thực tiễn và có những ưu thế riêng nhất định.
Ngôn ngữ lập trình C++ rất phù hợp để rèn luyện cho học sinh hiểu sâu về thuật toán cũng như phân tích, đánh giá chính xác hiệu suất thuật toán. Trong lập trình thi đấu ở chương trình trung học phổ thông, ngôn ngữ C++ là ngôn ngữ được lựa chọn hàng đầu.
Ngôn ngữ lập trình Python khá đơn giản giúp học sinh dễ học, dễ viết nhưng việc thực thi chương trình rất chậm không phù hợp với lập trình thi đấu trong giai đoạn hiện nay nhưng lại phù hợp hơn với định hướng giáo dục Stem của bộ môn Tin học (Sở GD&ĐT Nghệ An đã có công văn số 1677/SGD&ĐT- GDTrH ngày 26/8/2020 về hướng dẫn thực hiện giáo dục STEM trong trường trung học từ năm học 2020-2021)
6
Việc dạy học cho đối tượng học sinh khá giỏi cả 2 ngôn ngữ giúp các em thấy được sự đa dạng phong phú trong lĩnh vực lập trình; giúp các em có cái nhìn tổng quát, toàn diện hơn; biết ưu, nhược điểm của mỗi ngôn ngữ từ đó kích thích sự tìm tòi, khám phá thúc đẩy niềm đam mê say sưa với Tin học; giúp các em có định hướng nghề nghiệp sớm hơn và phấn đấu để đạt mục tiêu của mình.
3. Tầm quan trọng của chủ đề Xâu ký tự trong dạy học lập trình.
Chủ đề “Xâu dữ liệu” là một nội dung rất quan trọng trong việc tiếp cận ngôn ngữ lập trình bậc cao và cũng là yêu cầu thường gặp khi xây dựng các phần mềm ứng dụng thực tiễn.
Trong việc dạy học lập trình, giáo dục Stem, bồi dưỡng học sinh khá giỏi ở trường phổ thông, chủ đề Xâu dữ liệu là một nội dung trọng tâm. Học sinh cần nắm được các thao tác xử lý trên xâu, có kỹ năng tốt trong việc phân tích bài toán và lựa chọn phương pháp phù hợp để có chương trình tốt hơn cả về độ sáng sủa của thuật toán lẫn thời gian thực hiện chương trình. Để đạt được điều đó, giáo viên cần lựa chọn các ví dụ, bài tập đảm bảo tính mục đích, tính khả thi, tính hiệu quả; các bài toán đưa ra chứa đựng những mâu thuẫn cần giải quyết, gợi ra cho học sinh nhiều hướng suy nghĩ, nhiều cách giải quyết vấn đề. Thiết kế trình tự thực hiện các bài toán cũng được xem là cơ sở quan trọng trong việc truyền tải kiến thức và kỹ năng, cần chú ý vận dụng linh hoạt cho từng trường hợp cụ thể để đạt mục đích dạy học.
II - THỰC TRẠNG VẤN ĐỀ
1. Thực trạng dạy học ngôn ngữ lập trình C++, Python ở các trường THPT.
Ngôn ngữ lập trình C++, Python là ngôn ngữ được định hướng dạy học trong chương trình GDPT 2018 và được khuyến khích triển khai dạy học trong giai đoạn chuyển tiếp hiện nay nhưng việc thực hiện còn có một số khó khăn nhất định:
+ SGK hiện hành dùng ngôn ngữ lập trình Pascal để minh họa nên học sinh không có sách phù hợp để làm tài liệu học tập. Việc tìm kiếm tài liệu dạy học phù hợp trình độ học sinh rất vất vả.
+ Đối với giáo viên việc trao đổi, chia sẻ, học hỏi kinh nghiệm gặp nhiều khó khăn do hầu hết đội ngũ giáo viên đều quen với ngôn ngữ lập trình Pascal, chưa mạnh dạn chuyển sang dạy ngôn ngữ khác có tính ưu việt hơn.
+ Kiến thức về lập trình không nằm trong nội dung thi THPT quốc gia nên hầu hết học sinh không coi trọng, ít học bài và làm bài tập chỉ những học sinh đã yêu thích, đam mê mới đầu tư thời gian cho việc học lập trình. Vì thế lượng giáo viên đam mê chuyên môn, đầu tư thời gian trăn trở nghiên cứu cải tiến cách dạy, cách học không nhiều.
7
+ Thời lượng dành cho dạy học ngôn ngữ lập trình 1,5 tiết/tuần, để mô tả thuật toán giải các bài toán trên máy tính là rất ít để có thể hiểu rõ ràng và áp dụng thành thạo ngôn ngữ lập trình. Thêm vào đó, cơ sở vật chất chưa đáp ứng được nhu cầu học tập nên việc triển khai dạy học chỉ có thể giúp học sinh hiểu được cơ bản quá trình giải một bài toán trên máy tính, còn để tất cả học sinh tự giải một bài hoàn chỉnh là rất khó.
2. Thực trạng dạy học ngôn ngữ lập trình C++, Python ở trường chúng tôi.
Từ năm học 2018 - 2019 chúng tôi đã được tham dự các lớp tập huấn do sở GD & ĐT Nghệ An tổ chức về lập trình trên ngôn ngữ lập trình C++. Năm học 2019 – 2020 tiếp tục tham dự tập huấn và được khuyến khích triển khai dạy học ngôn ngữ C++ thay Pascal. Hào hứng thực hiện nhiệm vụ đổi mới của ngành, chúng tôi đã mạnh dạn đưa C++ vào dạy học ở một số lớp. Đến năm học 2020 – 2021, trường chúng tôi đã triển khai cho toàn bộ học sinh khối 11 trong chương trình chính khóa.
Trong năm học 2019-2020, chúng tôi đã tập hợp những học sinh có học lực khá giỏi, yêu thích lập trình, truyền cảm hứng cho các em, thành lập Câu lạc bộ Tin học. Bước đầu tổ chức cho các em học tập, trao đổi về lập trình trên 3 ngôn ngữ lập trình là C++, Scratch và Python. Đối với những em học sinh lớp 10 mới tham gia chúng tôi cho làm quen với ngôn ngữ lập trình Scratch để kích thích hứng thú và giúp các em làm quen với tư duy máy tính, sau đó chúng tôi cho tiếp cận dần với ngôn ngữ lập trình C++ và Python.
Trong quá trình triển khai thực hiện chúng tôi đã gặp rất nhiều khó khăn vướng mắc cả về kiến thức chuyên môn lẫn nghiệp vụ sư phạm. Với sự yêu nghề, nhiệt huyết với học sinh, tôi đã không ngừng tìm tòi, nghiên cứu trau dồi kiến thức đồng thời tích cực kết bạn với các đồng nghiệp trên mọi miền tổ quốc để giao lưu, học hỏi nâng cao trình độ. Qua quá trình này tôi cũng đã có những sáng kiến đem áp dụng mang lại kết quả rất khả quan, đã đúc rút thành những kinh nghiệm đáng chia sẻ.
3. Thực trạng dạy học chủ đề xâu dữ liệu cho đối tượng học sinh khá giỏi.
+ Chủ đề Xâu dữ liệu trong C++, Python có hệ thống khái niệm, câu lệnh, hàm xử lý đa dạng phong phú mà tài liệu tham khảo lại rất ít ỏi. Nên việc tìm tòi tài liệu, bài tập phù hợp với trình độ học sinh đã gặp rất nhiều khó khăn, việc tổng hợp bài tập và đề thi thành các dạng bài tập phục vụ giảng dạy mất rất nhiều thời gian. Đặc biệt đối với những giáo viên ít tham gia bồi dưỡng thì còn vất vả hơn nhiều.
+ Qua dạy học chủ đề Xâu dữ liệu những năm trước, tôi đã khảo sát các cấp độ nhận thức của học sinh cho kết quả như sau: Đa số học sinh chỉ đạt ở mức độ biết và hiểu, vận dụng được thì không đến 50% học sinh. Trong khi đó đối với học sinh khá giỏi yêu cầu cao hơn như viết được chương trình một số bài toán đơn giản; liên hệ được kiến thức về xâu với các tình huống trong thực tiễn và vận dụng dữ liệu kiểu xâu vào giải bài toán ứng dụng cụ thể.
8
Lo lắng trước thực tế đó, tôi đã đầu tư thời gian, không ngừng học hỏi, nghiên cứu xây dựng nội dung, lựa chọn phương pháp, kỹ thuật phù hợp để kích thích đam mê, hứng thú giúp học sinh hình thành kiến thức và phát triển các kỹ năng, năng lực lập trình một cách tốt nhất. Kết quả trong kỳ thi HSG những năm gần đây, học sinh của tôi đã đạt được kết quả đáng tự hào.
III – GIẢI PHÁP
1 – MỘT SỐ ĐẶC TÍNH VỀ XÂU VÀ HỆ THỐNG KIẾN THỨC CỐT LÕI.
1.1 Một số đặc tính khác nhau giữa Xâu trong C++ và trong Python.
Xâu trong C++ Xâu trong Python
- Là chuỗi ký tự trong bảng mã ASCII.
- Python hỗ trợ hoàn toàn cho bảng mã Unicode.
- Tên kiểu dữ liệu: str - Tên kiểu dữ liệu: string
- Các ký tự của xâu được đặt trong cặp nháy kép.
- Các ký tự của xâu được đặt trong cặp nháy đơn hoặc kép. Xâu trên nhiều dòng được đặt trong cặp 3 nháy đơn hoặc 3 nháy kép.
- Các ký tự trong xâu được đánh chỉ số từ trước ra sau bắt đầu từ 0 và đảo chiều âm từ sau về trước bắt đầu từ -1. - Các ký tự trong xâu được đánh chỉ số từ trước ra sau bắt đầu từ 0; không đánh chỉ số ngược.
- Khai báo: Trong Python không cần
khai báo, để tạo biến xâu ta chỉ cần gán
xâu cho biến đó. - Khai báo: Để sử dụng cần khai báo
biến xâu: string
- Trong Python, xâu là bất biến, không thể thực hiện các thao tác làm thay đổi giá trị của xâu - Trong C++ có thể thực hiện các thao tác làm thay đổi giá trị của xâu
- Python không có kiểu dữ liệu ký tự, một ký tự cũng thuộc kiểu xâu.
- Trong C++ có kiểu dữ liệu ký tự: char - Có thể thực hiện xóa, hoặc chèn ký tự theo chỉ số - Không thể thực hiện xóa, chèn ký tự theo chỉ số nhưng vẫn cho phép truy xuất ký thự theo chỉ số
- Không cho phép thực hiện phép nhân xâu với một số nguyên. - Cho phép thực hiện phép nhân xâu với một số nguyên.
1.2 Tóm tắt một số thao tác xử lý xâu trong C++
* Một số thao tác cơ bản với xâu trong C++
- Phép ghép nối xâu: +
- Phép so sánh: >, >=, <, <=, ==, !=
9
- Hàm lấy độ dài xâu s: s.length() hoặc s.size();
- Hàm sao chép trong xâu s từ chỉ số VT lấy n ký tự: s.substr(VT, n);
- Hàm chèn thêm vào xâu x vào xâu s tại vị trí VT: s.insert(VT, x);
- Hàm xóa trong xâu s từ chỉ số VT xóa đi n ký tự: s.erase(VT, n);
- Hàm tìm kiếm: tìm vị trí đầu tiên xuất hiện xâu x trong xâu s: s.find(x). Nếu xâu x không có trong xâu S thì kết quả = -1
- Hàm tìm kiếm ngược: tìm vị trí cuối cùng xuất hiện xâu x trong xâu s: s.rfind(x). Nếu xâu x không có trong xâu S thì kết quả = -1
- Hàm thay thế n ký tự từ vị trí VT của xâu s bởi xâu x: s.replace(VT,n,x);
- Hàm đổi ký tự thành ký tự hoa: toupper(ch);
- Hàm đổi ký tự thành ký tự thường: tolower(ch)
* Một số thao tác mở rộng với xâu trong C++
- Hàm chuyển xâu s thành số n kiểu int: n = atoi(s.c_str());
- Hàm chuyển xâu s thành số n kiểu long: n = atol(s.c_str());
- Hàm chuyển xâu s thành số n kiểu long long: n = atoll(s.c_str());
- Hàm chuyển xâu s thành số n kiểu float: n = atof(s.c_str());
- Hàm chuyển số n thành xâu s:
stringstream convert; covert << n; s = convert.str();
- Hàm s.size(); lấy chiều dài của xâu s.
- Hàm s.insert(VT, s1, n); Thêm n ký tự vào xâu s từ chuỗi s1 vào vị trí Vt. Nếu n có độ dài lớn hơn độ dài chuỗi s1 thì tiếp tục thêm vào 1 khoảng trắng và sau đó lại tiếp tục thêm các ký tự của s1cho đủ n ký tự.
- Hàm s.insert(VT, n, 'z'); Thêm n lần ký tự z vào vị trí VT.
- Hàm s.insert(s.begin() + x, s2.begin() + y, s2.begin() + z); Thêm chuỗi ký
tự con của chuỗi s2 bắt đầu từ vị trí y cho đến vị trí z - 1 vào vị trí x trong xâu s.
- Hàm s.erase(S.begin() + x); Xóa đi trong xâu S ký tự tại vị trí x.
- Hàm s.erase(s.begin() + x, s.begin() + y); Xóa đi các ký tự từ chỉ số x đến
chỉ số y – 1.
- s.find(x, vt): Tìm kiếm vị trí đầu tiên xuất hiện xâu x trong xâu s.
- s.rfind(x, vt): Tìm kiếm vị trí cuối cùng xuất hiện xâu x trong xâu s.
- Transform(s.begin(), s.end(), s.begin(), ::toupper); hàm chuyển tất cả các
ký tự trong xâu s thành chữ hoa.
- Transform(s.begin(), s.end(), s.begin(), ::tolower); hàm chuyển tất cả các
ký tự trong xâu s thành chữ thường.
10
- .....
1.3 Tóm tắt một số thao tác xử lý xâu trong Python
* Một số thao tác cơ bản với xâu trong Python
- Phép ghép nối xâu: +
- Phép so sánh: >, >=, <, <=, ==, !=
- Phép toán a in b: cho kết quả = True nếu a là xâu con của b, ngược lại thì
kết quả là False
- Thao tác cắt trích: s[start : end : step] lần lượt duyệt và trích các phần tử thuộc phạm vi từ vị trí start đến vị trí end-1 sau mỗi lần lấy một phần tử trong phạm vi thì di chuyển con trỏ với bước nhảy có độ rộng step. Các tham số trên có thể vắng mặt: nếu thiếu start thì mặc định là bắt đầu từ đầu xâu, thiếu end thì mặc định đến hết xâu, thiếu step thì mặc định là 1
- Hàm lấy độ dài xâu s: len(s);
- Sao chép trong xâu s: ta sử dụng thao tác cắt trích xâu để gán cho biến
khác.
- Chèn và Xóa xâu: Trong python không cho phép chèn vào xâu. Ta có thể
sử dụng hàm replace() hoặc thao tác cắt trích kết hợp ghép nối để xử lý.
- Hàm tìm kiếm: tìm vị trí đầu tiên xuất hiện xâu x trong xâu s: s.find(x).
Nếu xâu x không có trong xâu S thì kết quả = -1
- Hàm tìm kiếm ngược: tìm vị trí cuối cùng xuất hiện xâu x trong xâu s:
s.rfind(x). Nếu xâu x không có trong xâu S thì kết quả = -1
- Hàm thay thế: s.replace(s1, s2) thay thế xâu con s1 của xâu s bởi xâu s2
trả về một xâu mới.
- Hàm ord(ch): cho mã ASCII thập phân của ký tự ch.
- Hàm chr(x): cho ký tự có mã ASCII là x
- Hàm tạo xâu in hoa từ xâu s: s.upper()
- Hàm tạo xâu in thường từ xâu s: s.lower()
* Một số thao tác mở rộng với xâu trong Python
- Hàm tìm kiếm: s.find(sub, [start], [end]), với ý nghĩa tìm xâu con sub trong xâu s, vị trí bắt đầu tìm kiếm là start và vị trí kết thúc tìm kiếm là end, nếu vắng start thì mặc định bắt đầu tìm là vị trí 0 (cận trái) và nếu vắng end thì mặc định vị trí kết thúc tìm kiếm là cuối xâu. Nếu không tìm thấy thì kết quả = -1
- s.rfind(x, [start], [end]): Tìm kiếm vị trí cuối cùng xuất hiện xâu x trong
xâu s bắt đầu từ vị trí end-1, trở về vị trí start.
- Hàm thay thế: s.replace(s1, s2) để thay thế phần xâu con s1 bằng một xâu
11
s2, trả về một xâu mới.
- Hàm capitalize() viết hoa ký tự đầu tiên trong xâu, các chữ còn lại viết
thường
- Hàm s.strip(ch): trả về xâu mới có giá trị bằng xâu s đã xóa ký tự ch bên
trái, bên phải hoặc xóa ký tự bên trái, bên phải.
- Hàm s.startswith(x) Dùng để kiểm tra chuỗi s có bắt đầu bằng chuỗi con x
hay không
- Hàm s.endswith(x) Dùng để kiểm tra chuỗi s có kết thúc bằng chuỗi con x
hay không
- Hàm s.count(x) sẽ trả về số lần xuất hiện của chuỗi con x trong chuỗi mẹ s.
- Hàm ds = s.split(x): cắt xâu s thành nhiều chuỗi con, dựa vào tiêu chí ngăn cách để cắt là xâu x lưu vào list có tên ds. Nếu vắng mặt xâu x thì việc cắt dựa vào xâu con các dấu cách.
- Hàm s=x.join(ds): nối các xâu trong list ds thành xâu s bởi xâu gắn kết x.
2. RÈN LUYỆN KỸ NĂNG LẬP TRÌNH VỚI CHỦ ĐỀ KIỂU XÂU
Rèn luyện kỹ năng lập trình cho học sinh cần xây dựng các bài toán thành một hệ thống theo một trình tự logic có sự sắp đặt của phương pháp và quy trình giải toán, giúp học sinh dễ dàng tiếp cận với nội dung bài học, đồng thời có thể phát triển tư duy cũng như tạo ra niềm vui và sự hứng thú trong học tập.
2.1 Ôn luyện kỹ năng sử dụng thao tác xử lý xâu qua một số bài toán cơ bản
Để giúp học sinh ghi nhớ, khắc sâu và vận dụng linh hoạt các thao tác xử lý cơ bản trên xâu, tôi thường đưa ra các bài tập cơ bản rồi cho học sinh phân tích, tìm các cách giải quyết khác nhau. Những bài toán này không yêu cầu cao về mặt thuật toán mà cần huy động hết vốn kiến thức để có càng nhiều giải pháp càng tốt. Chương trình giải bài toán có nhiều cách diễn đạt khác nhau, giáo viên có thể yêu cầu các em diễn đạt hết các cách để rèn luyện kỹ năng diễn đạt câu lệnh.
Bài luyện tập 1:
Mục tiêu: Rèn luyện kỹ năng sử dụng các phép toán: ghép xâu, lấy độ dài
xâu, đảo xâu, duyệt thuận, duyệt ngược xâu:
Bài toán 1: Viết chương trình nhập vào một xâu ký tự S, đưa ra xâu đó
nhưng được viết theo chiều ngược lại.
Ý tưởng giải thuật:
Cách 1: Sử dụng phép toán ghép nối (+): Khởi tạo biến kq= “” Duyệt lần lượt các ký tự của xâu ghép nối vào xâu kq (việc duyệt
12
và ghép nối có thể có rất nhiều cách diễn đạt)
Cách 2: Sử dụng hàm đảo Xâu: trong C++ sử dụng hàm reverse, trong
Python dùng thao tác cắt trích s[start : end : step] .
Chương trình tham khảo viết bằng C++:
Ý tưởng sư phạm: Thông qua các chương trình nhấn mạnh cho học sinh các thao tác đã được vận dụng trong bài toán này và ý nghĩa, kỹ thuật sử dụng các thao tác.
- Hàm s.length(): lấy độ dài xâu s, ngoài ra s.size() cũng cho độ dài xâu s.
- Phép cộng (+): Ghép nối xâu.
- Hàm reverse(s.begin(), s.end()): Đảo xâu.
13
Chương trình tham khảo viết bằng Python:
Ý tưởng sư phạm:
Thông qua các chương trình nhấn mạnh cho học sinh các thao tác đã được vận dụng trong bài toán này và ý nghĩa, kỹ thuật sử dụng các thao tác trong Python.
- Hàm len(): lấy độ dài xâu s.
- Phép cộng (+): Ghép nối xâu.
- Thao tác Cắt trích: s[start : end : step]
Ý nghĩa là, lần lượt duyệt và trích các phần tử thuộc phạm vi từ vị trí start đến vị trí end-1 sau mỗi lần lấy một phần tử trong phạm vi thì di chuyển con trỏ với bước nhảy có độ rộng step. Các tham số trên có thể vắng mặt: nếu thiếu start thì mặc định là bắt đầu từ đầu xâu, nếu thiếu end thì mặc định đến hết xâu, nếu thiếu step thì mặc định là 1.
Bài luyện tập 2:
Mục tiêu:
Rèn luyện kỹ năng sử dụng thao tác ghép nối, tìm kiếm, thay thế; thao tác
xóa trong C++;
Bài toán 2:
Viết chương trình nhập vào một xâu ký tự S, đưa ra xâu đó nhưng loại bỏ
các dấu cách trống.
Ý tưởng giải thuật:
Cách 1: Sử dụng thêm biến kq để lưu kết quả:
Duyệt các phần tử, nếu gặp phần tử khác cách ‘ ’ thì nối sang xâu
kết quả.
Cách 2: Duyệt tìm các dấu cách trống rồi xóa khỏi xâu.
* Trong C++:
- Ta có thể duyệt từ sau ra trước bằng lệnh for hoặc while để
tìm và xóa dấu cách.
- Dùng hàm find tìm và xóa dấu cách bằng lệnh delete hoặc
lệnh replace.
* Trong Python: (không thể xóa phần tử theo chỉ số)
- Dùng hàm replace để thực hiện
- Dùng phép toán cắt trích kết hợp ghép nối.
14
Chương trình tham khảo bằng C++:
Ý tưởng sư phạm:
Thông qua bài tập rèn luyện cho học sinh sự nhìn nhận đa hướng, mỗi bài toán có rất nhiều cách giải quyết; nhấn mạnh, khắc sâu ý nghĩa, kỹ thuật sử dụng các thao tác xử lý xâu:
- Lưu ý hàm s.length() và hàm s.size() cùng cho độ dài xâu s.
- Hàm tìm kiếm:
+ s.find(x, vt): Tìm kiếm vị trí đầu tiên xuất hiện xâu x trong xâu s. bắt đầu từ vị trí vt trở đi, nếu không có tham số vt thì bắt đầu tìm từ đầu xâu. Nếu không tìm thấy thì kết quả = -1
15
+ s.rfind(x, vt): Tìm kiếm vị trí cuối cùng xuất hiện xâu x trong xâu s. bắt đầu từ vị trí vt trở về, nếu không có tham số vt thì bắt đầu tìm từ cuối (tìm ngược từ sau về đầu). Nếu không tìm thấy thì kết quả = -1
- Hàm thay thế:
+ s.replace(vt, n, x): thay thế n ký tự trong xâu s, tính từ vị trí vt bởi
xâu x.
Chương trình tham khảo viết bằng Python:
Ý tưởng sư phạm:
Thông qua bài tập này nhấn mạnh, khắc sâu ý nghĩa, kỹ thuật sử dụng các
thao tác xử lý xâu như phép ghép nối xâu, cắt trích xâu và hàm tìm kiếm, thay thế:
+ s.find(x, [start], [end]): Tìm kiếm vị trí đầu tiên xuất hiện xâu x trong xâu s. bắt đầu từ vị trí start, kết thúc ở vị trí end-1, nếu vắng start thì mặc định bắt đầu tìm là vị trí 0 và nếu vắng end thì mặc định vị trí kết thúc tìm kiếm là cuối xâu. Nếu việc tìm kiếm không có kết quả thì hàm trả về giá trị -1
+ s.rfind(x, [start], [end]): Tìm kiếm vị trí cuối cùng xuất hiện xâu x
- Hàm tìm kiếm:
trong xâu s bắt đầu từ vị trí end-1, trở về vị trí start. - Hàm thay thế:
+ s.replace(s1, s2) để thay thế phần xâu con s1 bằng một xâu
mới s2.
Bài luyện tập 3:
Mục tiêu: Rèn luyện kỹ năng sử dụng thao tác sao chép, chèn, xóa, tìm
kiếm, thay thế trong C++; thao tác cắt trích, ghép nối, thay thế trong Python.
Bài toán 3:
Viết chương trình nhập vào từ bàn phím xâu ký tự s, tìm và thay thế tất cả
các cụm ký tự s1 thành s2.
Ví dụ:
16
Xâu nhập vào: Xâu kết quả: s = “anh oi, anh dang o đau” s1= “anh”; s2= “em”; S = “em oi, em dang o đau”
Ý tưởng giải thuật: Cách 1:
- Trong C++: Dùng hàm tìm kiếm s.find(s1) để xác định vị trí xuất hiện xâu s1 trong xâu s: vt = s.find(s1) Nếu vt != -1 tức là có xâu s1 trong xâu s thì thay thế xâu s1 bởi xâu s2 bằng hàm s.replace(vt,l1,s2); hoặc thay thế bằng lệnh xóa và chèn: s.erase(vt,l1); s.insert(vt,s2);
Lưu ý: Trong xâu có thể có rất nhiều cụm từ cần thay thế nên ta phải sử
dụng lệnh while để thay thế hết: trong khi s.find(s1) != -1 thì tiếp tục thay thế
- Trong Python: Sử dụng thao tác cắt trích, so sánh và ghép nối để thực hiện ý tưởng trên.
Cách 2: - Trong C++:
Để duyệt hết tất cả các khả năng cần thay thế ta sử dụng lệnh for kết hợp lệnh s.substr() để sao chép từng đoạn con có độ dài bằng độ dài xâu s1 rồi so sánh với s1. Nếu kết quả bằng s1 thì ta tiến hành thay thế bằng các câu lệnh tương tự cách 1.
- Trong Python: Dùng hàm replace để thực hiện.
Chương trình tham khảo bằng C++ Chương trình 1: Chương trình 2:
Ý tưởng sư phạm:
Thông qua bài tập rèn luyện nhấn mạnh, khắc sâu ý nghĩa, kỹ thuật sử dụng
17
các thao tác xử lý xâu.
Chương trình tham khảo bằng Python:
Ý tưởng sư phạm:
Thông qua bài tập này nhấn mạnh, khắc sâu kỹ thuật sử dụng các thao tác cắt
trích, thay thế.
Bài luyện tập 4:
Mục tiêu: Rèn luyện kỹ năng xử lý ký tự theo mã ASCII, kỹ thuật đếm
phân phối trên mảng với kiểu chỉ số tương ứng các ký tự.
Bài toán 4: Đếm số lần xuất hiện mỗi loại ký tự.
Cho xâu s (có độ dài không vượt quá 103) chỉ gồm các ký tự từ 'A' đến 'Z'. Cho biết có bao nhiêu loại ký tự xuất hiện trong s và đưa ra một ký tự xuất hiện nhiều nhất trong s cùng với số lần xuất hiện của ký tự đó
Ý tưởng giải thuật:
- Các ký tự từ 'A' đến 'Z' có mã ASCII tương ứng từ 65 đến 90. Nên ta sử dụng mảng T gồm 91 phần tử với kiểu chỉ số từ 0 đến 90, kiểu giá trị int để lưu số lần xuất hiện: T[65] …T[90] tương ứng số lần xuất hiện ký tự ‘A’… ‘Z’.
- Lần theo các giá trị của mảng T trên đoạn từ 65 đến 90 ta được số lượng các ký tự khác nhau (tức số lượng phần tử có giá trị khác 0 trong mảng T) và tìm giá trị lớn nhất của mảng T ta sẽ tìm được ký tự xuất hiện nhiều lần nhất.
Về nguyên tắc, ta chỉ cần sử dụng mảng với 26 phần tử kiểu int với chỉ số từ 0 đến 25, khi đó với mỗi ký tự ta chuyển sang mã ASCII rồi dịch chuyển chỉ số 65 đơn vị. Chương trình tham khảo trong Python (cách 1) sau được viết với ý tưởng này.
18
Ngoài ra, trong Python ta có thể sử dụng lệnh count để đếm số lần xuất hiện không chồng lấn của một ký tự hay xâu con bên tròn xâu lớn. Chương trình tham khảo trong Python (cách 2) sau được viết với ý tưởng này.
Chương trình tham khảo:
Chương trình viết bằng Python (cách 1)
Chương trình viết bằng C++
Chương trình viết bằng Python (cách 2)
Ý tưởng sư phạm:
19
Thông qua bài tập này nhấn mạnh cách thức sử dụng bảng mã ASCII, cách chuyển đổi qua lại giữa mã thập phân và ký tự, kỹ thuật đếm phân phối trên mảng với kiểu chỉ số tương ứng các ký tự. Ngoài ra, cần nhấn mạnh lệnh khởi tạo toàn bộ phần tử của mảng = 0, trong chương trình trên là lệnh memset, lệnh nhân (*). Lưu ý thêm lệnh ý nghĩa và cách sử dụng lệnh count trong Python.
2.2 - Rèn luyện kỹ năng giải một số dạng bài tập phổ biến về xâu ký tự:
Việc phân loại dạng bài tập chỉ mang tính tương đối, một bài tập ở dạng này hay dạng kia còn phụ thuộc rất nhều vào cách nhìn nhận đa chiều của người lập trình. Trong phạm vi đề tài này mục tiêu của tôi là rèn luyện cho học sinh một số định hướng để giúp học sinh cái nhìn tổng quan hơn, nên mỗi bài toán có thể được đề xuất nhiều cách giải từ đó học sinh có thể phân tích, lựa chọn giải pháp tốt hơn để giải quyết bài toán. (Các giải pháp được đề xuất chỉ là các cách giải quyết, chưa hẳn đã là giải pháp tối ưu để giải bài toán)
2.2.1 Dạng bài tập yêu cầu biến đổi xâu
Đâ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, các hàm xử lý 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 tập 1: Chuyển đổi phông chữ:
Khi soạn thảo và trình bày văn bản, việc chuyển đổi đoạn văn chữ hoa
sang thường hay chữ thường sang chữ hoa là một nhu cầu rất phổ biến.
Em hãy viết chương trình nhập vào 1 xâu s chỉ chứa dấu cách và các ký tự thuộc bảng chữ cái tiếng Anh, Hãy tạo xâu s1 chứa các tự trong xâu s nhưng ở dạng chữ hoa, tạo xâu s2 chứa các tự trong xâu s nhưng ở dạng chữ thường. Xuất kết quả xâu s1, s2 ra màn hình.
Ý tưởng giải thuật:
Cách 1: Duyệt và chuyển đổi từng ký tự:
Trong C++: Dùng hàm toupper(), tolower() để chuyển đồi từng ký tự hoặc biến
đổi qua mã ASCII.
Trong Python: Sử dụng hàm ord() và chr() để thực hiện.
Cách 2: Dùng hàm chuyển đổi đồng loạt
Trong C++: Dùng hàm transform() để chuyển đồi tất cả các ký tự.
+ transform(s.begin(), s.end(), s.begin(), ::toupper); chuyển xâu s sang chữ hoa
+ transform(s.begin(), s.end(), s.begin(), ::tolower); chuyển xâu s sang chữ thường
Trong Python: Dùng hàm upper(), lower().
+ s.upper() Hàm này trả lại xâu s sau khi chuyển tất cả các ký tự thành chữ hoa.
20
+ s.lower() Hàm này trả lại xâu s sau khi chuyển tất cả các ký tự thành chữ thường.
* Chương trình tham khảo trong C++:
Chương trình 2: Chương trình 1:
* Chương trình tham khảo trong Python:
Ý tưởng sư phạm: Rèn luyện kỹ năng vận dụng hàm chuyển đổi ký tự sang ký tự hoa toupper(), ký tự thường tolower(), hàm chuyển đổi đồng loạt sang chữ hoa, chữ thường tranform() trong C++.
Trong Python chuyển đổi chữ hoa, chữ trường dựa vào mã ASCII và hàm
21
chuyển đổi xâu sang in hoa, in thường upper(), lower().
Bài tập 2: Xóa dấu cách thừa:
Khi soạn thảo và trình bày văn bản, một số bạn thường mắc lỗi gõ nhiều
dấu cách giữa các từ.
Em hãy viết chương trình nhập vào 1 xâu s, Hãy đưa ra xâu đã loại dấu
cách thừa.
Ý tưởng giải thuật:
Ta hoàn toàn có thể duyệt xâu rồi xóa các ký tự cách liền nhau như chúng ta thường làm trong ngôn ngữ lập trình Pascal. Nhưng ở đây ta sringstream của C++ và thao tác split(), join() trong Python để chương trình đơn giản hơn.
* Chương trình tham khảo:
Chương trình viết bằng C++ Chương trình viết bằng Python
Ý tưởng sư phạm:
Rèn luyện kỹ năng vận dụng stringstream trong C++ và thao tác tách split(), nối join(). Thao tác này rất hữu ích trong việc giải quyết một số bài toán về xâu.
Bài tập 3: Mã hóa Xê Da (sách bài tập tin học 11)
22
Để giữ bí mật người ta phải mã hóa các thông tin trước khi truyền đi hoặc lưu trữ. Một trong những cách mã hóa sớm nhất được sử dụng rộng rãi thời cổ đại là cách mã hóa do Xê Da đề xuất: trong thông điệp, người ta thay đổi chữ cái bằng chữ cái đứng sau nó K vị trí trong bảng chữ cái. Việc tìm kiếm thay thế được tiến hành vòng tròn theo bảng chữ cái. Nếu bảng chữ cái có N chữ, thì sau chữ cái thứ N-1 là chữ cái N, sau chữ cái N là chữ cái thứ nhất,… Cách mã hóa này gọi là mã Xê Da. Các kí tự ngoài bảng chữ cái vẫn được giữ nguyên.
Ví dụ, bảng chữ cái tiếng Anh có 26 chữ cái. Nếu K = 2 thì có nghĩa là a được thay thế bằng c, b được thay thế bằng d, . . ., y được thay thế bằng a, z được thay thế bằng b. Các chữ cái in hoa sẽ được thay thế bằng chữ cái in hoa tương ứng. Trong trường hợp này, từ ‘TIN HOC’ sẽ được mã hóa thành ‘VKP JQE’ .
Hãy lập trình: Nhập vào từ bàn phím số nguyên K (1 Ý tưởng giải thuật: Để dễ xử lý hơn khi dịch k ký tự theo vòng tròn, ta dùng thêm 2 biến phụ S1 để lưu 2 lần bảng chữ cái in hoa. S2 lưu 2 lần bảng chữ cái in thường. Duyệt từng ký tự trong xâu s, tìm vị trí xuất hiện của nó trong xâu s1, s2. Nếu tìm thấy thì ta lấy ký tự cách nó k ký tự trên mảng tương ứng. Chương trình tham khảo: Chương trình viết bằng C++ Chương trình viết bằng Python Ý tưởng sư phạm: 23 Rèn luyện kỹ năng sử dụng bảng mã ASCII để giải quyết một số bài toán.
Qua đây nhấn mạnh cho học sinh cách chuyển đổi ký tự sang mã thập và từ mã
thập phân sang ký tự. Trong C++ ta ép kiểu, trong Python ta dùng hàm ord(),
chr(), qua ví dụ này nhấn mạnh hơn với học sinh về phép toán nhân (*) xâu. 2.2.2 Dạng bài tập có yêu cầu duyệt xử lý xâu con. Duyệt xâu con trên xâu ký tự là một yêu cầu thường gặp khi giải các bài
toán, có nhiều cách thực hiện duyệt khác nhau, để giải quyết các bài toán dạng
này học sinh phải có kỹ năng nhận dạng, phân tích bài toán rồi lựa chọn thuật
toán thích hợp để giải quyết. Bài tập 1: Xâu con dài nhất Cho xâu S, tìm xâu con liên tục dài nhất của xâu S mà không chứa chữ số
nào. Kết quả đưa ra vị trí đầu và xâu con đó. Nếu có nhiều xâu con dài nhất thì
đưa ra xâu đầu tiên. Ý tưởng giải thuật: Có rất nhiều giải thuật để duyệt tìm xâu con dài nhất thỏa mãn một điều kiện nào đó. Cách 1: Duyệt vét cạn thử với mọi xâu con để tìm xâu con dài nhất. Sử dụng hai vòng for lồng nhau duyệt từ đầu đến hết xâu với mỗi cặp chỉ
số đầu i và chỉ số j. Ta kiểm tra có thỏa mãn điều kiện hay không, rồi so sánh
tìm xâu con thỏa mãn dài nhất. Cách 2: Duyệt theo các xâu con với độ dài từ lớn đến bé. Ta duyệt các xâu con với độ dài từ độ dài xâu mẹ giảm dần. Khi gặp xâu
con đầu tiên thỏa mãn điều kiện thì đây chính là xâu cần tìm và ta kết thúc việc
duyệt bằng lệnh break; Cách 3: Duyệt phát triển xâu con: Lần lượt duyệt lần lượt các ký tự trong xâu, dùng biến lmax để lưu độ dài
xâu lớn nhất đã tìm được, nếu gặp ký tự thỏa mãn (không phải số) ta tăng dần độ
dài xâu con. Khi gặp ký tự không thỏa mãn (ký tự số) thì ta thu được một xâu
con thỏa mãn điều kiện, đem độ dài xâu này so sánh với lmax đã lưu để cập nhật
lại lmax mới. Đây là 3 cách duyệt xâu con, đoạn con dài nhất phổ biến. với từng bài
toán cụ thể các mô tả về xâu con, đoạn con lại khác nhau và lúc đó phương pháp
duyệt tốt nhất lại khác nhau, ta cần phân tích cân nhắc kỹ càng để lựa chọn thuật
toán tốt nhất. Với bài toán này ta sử dụng cách 3 duyệt theo phát triển xâu con với độ phức tạp o(n). 24 Các chương trình tham khảo sau được viết theo ý tưởng này: Chương trình viết bằng C++ Chương trình viết bằng Python Ý tưởng sư phạm: Qua bài tập này phân tích cho học sinh: + Một số hướng giải dạng bài toán tìm xâu con dài nhất thỏa mãn một
điều kiện nào đó, đây cũng là một dạng toán thường gặp trong các đề thi. Việc
lựa chọn thuật giải nào còn phụ thuộc vào điều kiện cụ thể. + Lưu ý học sinh về cách sử dụng các hàm: isdigit(), isalpha() Bài tập 2: Đảo từ trong xâu Cho xâu ký tự s, từ là một xâu con liên tiếp không chứa dấu cách. Một xâu ký tự có thể gồm nhiều từ. Em hãy viết chương trình nhập vào xâu ký tự s. Đưa ra xâu đó với các từ được viết theo chiều ngược lại. Ví dụ: s = “di xe dap” thì kết quả là: kq =“dap xe di” Ý tưởng giải thuật: 25 Cách 1: Duyệt trên từng ký tự của xâu: Duyệt ngược xâu từ sau ra trước,
mỗi lần tìm thấy dấu cách hoặc ký tự đầu tiên của xâu, thì đọc các ký tự từ vị trí
đó đến vị trí dấu cách đã gặp trước đó. Cách 2: Duyệt tìm vị trí chứa các dấu cách copy xâu con giữa 2 dấu cách rồi nối vào xâu kết quả. Cách 3: (dành riêng cho Python) tách xâu thành các xâu con lưu vào list, sau đó thực hiện đảo chiều list rồi nối lại thành xâu kết quả Chương trình tham khảo: Sau đây là chương trình thể hiện ý tưởng cách 2 bằng C++ và cách 3 bằng Chương trình cách 3 bằng Python Python Ý tưởng sư phạm: Qua bài toán này lưu ý học sinh: + Khi diễn tả thuật toán ta cần chú ý trau chuốt từng câu lệnh để chương
trình trở nên ngắn gọn, sáng sủa hơn. Ví dụ trong chương trình trên việc nội
thêm dấu cách vào trước và sau xâu nhập vào đã giúp việc diễn tả trở nên đơn
giải hơn. + Khi dùng hàm find() trong vòng lặp chúng ta cần cân nhắc lựa chọn có
hay không tham số vị trí bắt đầu tìm, vì một số trường hợp có thể dẫn đến việc
máy phải tìm đi tìm lại một đối tượng trên xâu nhiều lần do nguyên lý hoạt động
của hàm find(). Chúng ta cần giám sát để khéo léo loại tình huống đó. + Cũng qua bài toán này ta thấy việc sử dụng linh hoạt các hàm của 26 Python có thể thu được chương trình rất ngắn gọn, sáng sủa. Bài tập 3: Đếm xâu con (có chồng lấn và không chồng lấn lên nhau) Viết chương trình nhập vào 2 xâu ký tự s1, s2. Hãy cho biết số lần xuất
hiện xâu s2 trong xâu s1 không chồng lấn và số lần xuất hiện xâu s2 trong s1 có
chồng lấn. Ví dụ:
Kết quả: s1= “ababababaab” S2= “aba”
Số lần xuất hiện không chồng lấn là: 2
Số lần xuất hiện có chồng lấn là: 4 Ý tưởng giải thuật: Cách 1: Sử dụng hàm tìm kiếm sự xuất hiện xâu s2 trong xâu s1. Khi tìm
thấy s2 trong s1, ta xóa (hoặc thay thế bởi xâu “”) toàn phần tìm thấy hoặc 1 ký
tự tại vị trí tìm thấy rồi tìm tiếp. Nếu dung câu lệnh find() có tham số vị trí bắt
đầu thì không cần xóa. Cách 2: Ta có thể dùng lệnh while duyệt sao chép đoạn con của s1 có độ
dài bằng l2 (độ dài xâu s2) để so sánh với s2, trong yêu cầu 1 nếu tìm thầy thì ta
nhảy qua l2 vị trí tiếp theo. Ngoài ra trong Python ta có thể sử dụng lệnh count() để đếm số lần xuất Chương trình cách 1 bằng C++ Chương trình cách 2 bằng Python 27 hiện không chồng lấn. Ý tưởng sư phạm: Qua bài toán này tôi muốn nhấn mạnh với học sinh: + Có thể cùng một ý tưởng giải thuật nhưng có rất nhiều cách diễn tả. Cần
trau chuốt từng câu lệnh để chương trình chạy nhanh hơn, sáng sủa hơn. Ở đây
tôi cố ý diễn đạt với nhiều cách khác nhau để học sinh thấy rõ hơn về vấn đề
này.
+ Qua bài này học sinh biết thêm về câu lệnh count() trong Python có
chức năng đếm số lần xuất hiện không chồng lấn của một xâu ký tự hay xâu con
bên trong một xâu lớn. 2.2.3 Dạng bài tập có yêu cầu xử lý số lớn. Có rất nhiều bài toán cho dưới dạng số nhưng nếu chỉ dùng số hoặc mảng
số thì việc xử lý nó rất khó khăn thậm chí không thể thực hiện được, trong khi
đó nếu ta biết cách dùng xâu để xử lý thì công việc trở nên thuận lợi hơn rất
nhiều. Bài tập 1: Cho số nguyên dương N (số chữ số của N không quá 106). Hãy tính
tổng các số chẵn trong dãy. Ý tưởng: Số nguyên N có giá trị quá lớn nên ta không thể xử lý N theo kiểu
số. vì vậy ta đọc N vào xâu ký tự để giải quyết. Để kiểm tra tính chẵn lẻ và tính
tổng các chữ số, ta xử lý trên mã ASCII của các ký tự số. Chương trình viết bằng C++ Chương trình viết bằng Python Chương trình tham khảo: Ý tưởng sư phạm: Thông qua bài toán: + Lưu ý với học sinh một số tình huống cần sử dụng dữ liệu kiểu xâu giải quyết bài toán kiểu số. + Trong C++ khi thực hiện các phép toán trên ký tự nó sẽ hiểu là thực 28 hiện tính toán với mã ASCII của ký tự đó. Bài tập 2: Xóa số: Cho 2 số nguyên dương N và k (số chữ số của N không quá 106, k nhỏ
hơn số chữ số của N) Yêu cầu: Hãy tìm cách xóa k chữ số của N để các chữ số
còn lại (vẫn dữ nguyên thứ tự) tạo thành một số có giá trị lớn nhất. Ý tưởng: Vì giá trị của N quá lớn nên ta phải giải quyết với kiểu dữ liệu kiểu xâu.
Việc xóa đi k chữ số để lấy các chữ số còn lại thì kết quả cũng tương đương với
việc chọn N-k chữ số đúng trật tự để thu được kết quả là số lớn nhất. Để tìm chữ số lớn nhất cần lấy, ta xây dựng hàm vtm(i,j) đưa vào vị trí
đầu và cuối i-j, lấy ra vị trí phần tử lớn nhất đầu tiên thuộc đoạn i-j. Lần đầu
tiên lấy phần tử max chỉ số vt trong đoạn [0, k], sau đó tìm max với chỉ số đầu
[vt+1, k+1]… Chương trình tham khảo như sau: Chương trình viết bằng C++ Chương trình viết bằng Python 29 Ý tưởng sư phạm:
Thông qua bài toán trên, lưu ý với học sinh về 2 chương trình con tìm vị
trí max ở trên được xây dựng với 2 ý tưởng thiết kế khác nhau. Việc sử dụng
xâu phụ so= “9876543210” có thể mang lại lợi ích nhất định trong một số tình
huống. Bài tập 3: Ghép số Cho n số nguyên dương a1, a2, . . .,an (1 < n ≤ 100), mỗi số không vượt
quá 109 . Từ các số này người ta tạo ra một số nguyên mới bằng cách ghép tất
cả các số đã cho, tức là viết liên tiếp các số đã cho với nhau. Ví dụ, với n = 4 và
các số 123, 124, 56, 90 ta có thể tạo ra các số mới sau: 1231245690,
1241235690, 5612312490, 9012312456, 9056124123,... Có thể dễ dàng thấy
rằng, với n = 4, ta có thể tạo ra 24 số mới. Trong trường hợp này, số lớn nhất có
thể tạo ra là 9056124123. Yêu cầu: Cho n số nguyên số a1, a2, . . .,an nằm trên cùng 1 dòng. Hãy xác định số lớn nhất có thể tạo ra khi ghép các số đã cho thành một số mới. Ý tưởng: Lưu các số dưới dạng mảng kiểu xâu, thực hiện sắp xếp mảng theo thứ tự
tăng dần theo tiêu chí sắp xếp là phần tử a[i] đứng trước phần từ a[j] khi (a[i]
ghép với a[j]) > (a[j] ghép với a[i]). Chương trình tham khảo như sau: Chương trình viết bằng C++ Chương trình viết bằng Python 30 Ý tưởng sư phạm: Thông qua bài toán trên, nhấn mạnh với học sinh về nguyên
tắc so sánh 2 xâu, câu lệnh swap tráo đổi giá trị 2 xâu trong C++ và câu lệnh
gán đồng thời để tráo đổi giá trị trong Python. Bài tập 4: SỐ MỘT Xét các số nguyên dương K có dạng biểu diễn ở hệ thập phân có N chữ số và chỉ bao gồm các chữ số 1, ví dụ với N = 2 có K = 11, N = 3 có K = 111. Yêu cầu: Với N cho trước, tính K2 ( 1 ≤ N ≤ 103) Ví dụ: Với N = 9 thì K =111111111 Kết quả: K2 = 12345678987654321 Ý tưởng: Vì số lượng chữ số N của số K là rất lớn, nên ta không thể xử lý theo dữ liệu kiểu số mà phải xử lý theo dữ liệu kiểu xâu. Nhớ nguyên tắc thực hiện phép nhân một số với số có nhiều chữ số: ta
lấy số đó nhân lần lượt với mỗi chữ số của số nhân từ phải sang trái, với mỗi kết
quả ta đặt dịch sang trái thêm một hàng, cộng dọc các kết quả theo hàng từ phải
sang trái ta có kết quả. Với bài toán này số K chỉ gồm các chữ số 1, nên kết quả
của hàng i (i tăng dần từ 1 đến n sau đó giảm dần từ n-1 về 1) chính là tổng của
i số 1 và giá trị nhớ của hàng bên trái. Chương trình tham khảo như sau: Chương trình viết bằng C++ Chương trình viết bằng Python Ý tưởng sư phạm: 31 Thông qua bài bài toán này nhấn mạnh nguyên tắc thực hiện các phép
toán số học với kiểu dữ liệu xâu, sau đó yêu cầu học sinh viết chương trình cụ
thể để thực hiện phép toán số học trên 2 số nguyên lớn (lưu trử với kiểu xâu). 3 - MỘT SỐ BÀI TẬP MỞ RỘNG VÀ NÂNG CAO Việc rèn luyện kỹ năng lập trình cho học sinh cần thực hiện thường
xuyên, liên tục. Các bài tập để học sinh rèn luyện thường lấy từ ba nguồn chính:
Thứ nhất: Hệ thống bài tập do giáo viên tự phát biểu, xây dựng, chọn lọc và chỉnh sửa với mục đích, ý đồ sư phạm cụ thể trong mỗi bài. Thứ hai: Hệ thống đề thi học sinh giỏi các cấp. Nguồn bài tập này thường
có bộ test chuẩn, phân loại được độ phức tạp của thuật toán và đã được các tổ
chức phê duyệt. Sau khi học sinh giải đề thì tiến hành chấm bài tự động bằng
phần mềm Themis của thầy Lê Minh Hoàng để phân tích, đánh giá và rút kinh
nghiệm. Thứ ba: Hệ thống bài tập từ các website giải bài trực tuyến, với các trang
website này có hệ thống bài tập đa dạng, phong phú. Có phân loại theo dạng và
mức độ. Học sinh có thể viết chương trình trên nhiều ngôn ngữ lập trình khác
nhau và tiến hành chấm bài tự động online. Có rất nhiều trang cho học sinh làm bài tập và chấm bài như: http://thptchuyen.ntucoder.net/;
https://vnoi.info/problems/list/; http://laptrinhphothong.vn/;
http://vinhdinhcoder.net/;
http://ntucoder.net/; ….. Trong quá trình học sinh luyện tập giáo viên cần theo dõi, hướng dẫn
phân tích, nhận xét đánh giá bài làm của học sinh không chỉ về vấn đề thuật
toán mà uốn nắn cả những tiểu tiết cải tiến chương trình. Sau đây là một số bài tập và gợi ý giải để học sinh luyện tập: một số bài
được lấy trong các đề thi cấp tỉnh; một số đề do giáo viên biên soạn, lựa chọn
và chỉnh lý theo mục đích sư phạm; một số bài tập lấy trên trang giải bài tập và
chấm bài trực tuyến: Bài 1. LT0103 - PASSWORD (http://laptrinhphothong.vn/Problem/Details/5839) Yêu cầu: Cho một mật khẩu là một chuỗi các kí tự. Hãy đánh giá độ bảo mật của mật khẩu đó. Biết một mật khẩu hợp lệ có ít nhất 5 kí tự, chỉ bao gồm chữ cái và chữ số (không phân biệt chữ thường hay in hoa). Nếu mật khẩu hợp lệ in ra độ dài của chuỗi là độ bảo mật của mật khẩu. Nếu không in ra "Error!". Dữ liệu: Một dòng là xâu kí tự S có độ dài nhỏ hơn 1000 ký tự. Kết quả: Độ bảo mật của mật khẩu hoặc "Error!".
Ví dụ Input Output 32 provip123 9 Gợi ý: Trước hết kiểm tra độ dài xâu, nếu độ dài xâu dưới 5 ký tự thì in ra
"Error!" rồi kết thức chương trình. Ngược lại thì ta kiểm tra trong xâu có tồn tại
ký tự ngoài bảng chữ cái, chữ số. Để kiểm tra ký tự không thuộc bảng chữ cái, chữ số ta có thể sử dụng mã ASCII hoặc dùng hàm isalpha(), isdigit() để xác định. Bài 2. Rút gọn xâu (Đề thi HSG lớp 12 tỉnh Nghệ An năm 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 XAUGON.OUT hhooocccsssiiiiinnnhhh hocsinh * Gợi ý: Sử dụng xâu S để lưu xâu đầu vào, xâu phụ kq để lưu kết quả dầu ra.
Duyệt các ký tự từ đầu xâu đến cuối xâu, nếu gặp 2 ký tự liên tiếp khác nhau
S[i]!=S[i+1] thì ghép nối S[i] vào xâu kết quả. Bài 3. Xâu con ĐỒNG NHẤT 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.INP gồm 1 dòng chứa xâu ký tự S với độ dài
không quá 104 ký tự. Hãy đưa ra xâu con đồng nhất có độ dài lớn nhất của xâu
S. Nếu có nhiều xâu con thỏa mãn thì đưa ra xâu đầu tiên tính từ trái sang phải. Kết quả ghi vào tệp Dong_nhat.OUT gồm 1 dòng là xâu con tìm được. Ví dụ: Dong_nhat.Inp Dong_nhat.OUT hooocc ooo * Gợi ý: Khi 1 xâu đồng nhất thì các xâu con của nó cũng đồng nhất nên ta sẽ vận 33 dụng phương pháp phát triển xâu con để duyệt và tìm xâu con dài nhất. Sử dụng biến lmax để lưu lại độ dài lớn nhất, biến luui để chỉ vị trí cuối
cùng của xâu con dài nhất đã tìm được, biến dem để đếm số lượng các phần tử
đồng nhất đang xét. Lần lượt duyệt các ký tự trong xâu, nếu gặp ký tự thỏa mãn
(S[i] = S[i+1]) ta tăng dem. Khi gặp ký tự S[i]!=S[i+1] thì ta so sánh dem với
lmax, nếu dem > lmax thì cập nhật lại lmax mới và lưu lại vị trí cuối luui=i rồi
khởi tạo dem=0 để bắt đầu tìm đoạn đồng nhất mới. Khi duyệt hết xâu, kết quả
chính là xâu con từ chỉ số luui-lmax+1 đến luui của xâu S. Bài 4. 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. 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
MMAABBBEEEEZH NENXAU.OUT
2M2A3B4EZH * Gợi ý: Bài toán này ta có điểm tương tự bài toán 2 ở trên, ta vận dụng phương
pháp phát triển xâu con để giải quyết bài toán. Khi kết thúc đoạn đồng nhất ta
chuyển dem sang dạng xâu rồi thêm vào ký tự S[i] sau đó nối vào xâu kết quả.
Khi duyệt hết các ký tự trong xâu, ta thu được xâu cần tìm. Bài 5. Xâu ĐỐI XỨNG Xâu đối xứng là xâu đọc giống nhau nếu ta đọc từ trái qua phải hoặc từ phải qua trái. Ví dụ: xâu RADAR là xâu đối xứng. Kiểm tra xem một xâu có phải là xâu đối xứng hay không, nếu đối xứng thì thông báo là 1, nếu không đối xứng thì thông báo là 0. Dữ liệu: Vào từ file văn bản BAI2.INP, gồm: - Dòng đầu tiên ghi một số nguyên N. - N dòng tiếp theo mỗi dòng ghi các xâu cần kiểm tra. Kết quả: Ghi ra file văn bản BAI2.OUT: gồm N dòng, mỗi dòng ghi 0 nếu xâu tương ứng không đối xứng hoặc ghi 1 nếu xâu tương ứng đối xứng. 34 Giới hạn: 0 < N < 30000; Các xâu có độ dài không quá 255 kí tự. Ví dụ: BAI2.INP
3
AFHFA
ACDDB
ACRTT BAI2.OUT
1
0
0 * Gợi ý: Với yêu cầu của đề bài ta thấy cần kiểm tra đối xứng của nhiều xâu, nên
ta xây dựng làm KTDX(s) đầu vào là 1 xâu ký tự s, lấy ra là 1 nếu xâu đó đối
xứng, lấy ra 0 nếu xâu đó không đối xứng. Để kiểm tra xâu S có độ dài l có đối xứng hay không, ta dùng vòng for
biến i duyệt các phần tử từ 0 đến l/2. Với mỗi i ta so sánh S[i] với S[l-i-1], khi
gặp cặp ký tự này khác nhau, thì return 0, nếu hết vòng for không gặp cặp ký tự
nào khác nhau thì return 1. Đọc số nguyên n (lưu ý sau khi đọc n phải có lệnh xuống dòng) Lần lượt đọc mỗi dòng trong n dòng vào xâu s rồi ghi kết quả KTDX(s) vào tệp kết quả. Bài 6. 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 quá 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: 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
14 Bai2.inp
Ky thi hoc sinh gioi Tinh mon tin hoc
hoc sinh gioi mon Tin hoc 35 Gợi ý: Đây là bài toán tìm xâu con dài nhất của một xâu trong xâu còn lại. Ta sẽ
sử dụng cách duyệt theo phương pháp kiểm tra độ dài để kiểm tra sự xuất hiện
của xâu con ở xâu ngắn hơn trong xâu còn lại Bài 7: Chuẩn hóa văn bản: Một văn bản được gọi là văn bản chuẩn nếu: - Hai từ liền nhau có duy nhất một dấu cách trống. - Dấu ngắt câu (dấu chấm, dấu phẩy, dấu chấm phẩy, dấu chấm hỏi, dấu chấm than) được đặt sát vào từ ngay trước nó, sau đó mới đến dấu cách trống. - Dấu mở ngoặc đặt sát vào phía bên trái của từ bắt đầu mở ngoặc. - Dấu đóng ngoặc đặt sát bên phải từ cuối cùng được đóng ngoặc. Hãy viết chương trình nhập vào 1 xâu văn bản, đưa ra xâu đó ở dạng văn bản chuẩn. Gợi ý: - Xóa các dấu cách thừa: thực hiện như bài tập 2 của mục 2.2.1 hoặc có thể dùng lệnh for lùi duyệt để tìm và xóa. - Xử lý với các dấu câu: + Dùng xâu phụ để chứa các dấu câu: s1=".,;?!)"; + Duyệt từng ký tự i của xâu s: +/ Nếu s[i] có mặt trong xâu s1 thì xóa dấu cách phía trước nếu có và thêm dấu cách phía sau nếu chưa có. +/ Nếu s[i] là dấu ngoặc mở thì xóa dấu cách phía sau nếu có và thêm dấu cách phía trước nếu chưa có. Bài 8. ĐOẠN MAX (Đề thi HSG tỉnh lớp 12 năm học 2013 – 2014) Cho chuỗi kí tự S gồm toàn các chữ cái in hoa (A…Z) với độ dài không vượt quá 104. Yêu cầu: Hãy tìm đoạn con các kí tự liên tiếp dài nhất sao cho không có
kí tự nào xuất hiện nhiều hơn một lần. Trong trường hợp có nhiều hơn một đoạn
con có cùng chiều dài dài nhất, hãy chỉ ra đoạn xuất hiện đầu tiên trong chuỗi S. Dữ liệu: Vào từ văn bản DOANMAX.INP: - Gồm một dòng duy nhất chứa chuỗi S. Kết quả: Ghi ra file văn bản DOANMAX.OUT - Chỉ một dòng duy nhất chứa số nguyên P và L tương ứng là vị trí và chiều dài của đoạn con dài nhất tìm được. Ví dụ: DOANMAX.INP DOANMAX.OUT 36 ABABCDAC 3 4 Gợi ý: Với bài toán này ta sử dụng phương pháp kiểm tra theo độ dài. Vì đoạn con yêu cầu các ký tự xuất hiện không lớn hơn một lần nên ta chỉ cần kiểm tra các xâu có độ độ dài từ 26 trở xuống. Để kiểm tra tính duy nhất của mỗi ký tự trong dãy con, ta xây dựng hàm
KT(i,j) trả về giá trị True khi mỗi ký tự trong đoạn i,j là duy nhất. Ta có thể sử
dụng mảng đánh dấu với chỉ số tương ứng từ A-Z để phát hiện một ký tự trong
đoạn con đã xuất hiện để trả nhanh về giá trị false. Bài 9: Quản lý thi: Trong công tác tổ chức các kỳ thi, để đảm bảo tính khách quan, công bằng
cho các thí sinh, một công đoạn hết sức quan trọng là lập danh sách dự thi và
đánh số báo danh. Để đánh số báo danh, danh sách thí sinh phải được sắp xếp
với tên theo bảng chữ cái. Em hãy viết chương trình giúp cán bộ làm công tác thi sắp xếp danh sách thí sinh theo bảng chữ cái. Dữ liệu: Vào từ file văn bản THISINH.INP, gồm: - Dòng đầu tiên ghi một số nguyên N. - N dòng tiếp theo mỗi dòng ghi một xâu là họ và tên của thí sinh. Kết quả: Ghi ra file văn bản THISINH.OUT: gồm N dòng, mỗi dòng ghi họ tên của một thí theo thứ tự tên đã được sắp xếp theo bảng chữ cái. Giới hạn: 0 < N < 30000; Ví dụ: THISINH.INP THISINH.OUT 3 Tran Thi An Hoang Thi Hoa Hoang Thi Hoa Nguyen Van Thuy Nguyen Van Thuy Tran Thi An Gợi ý: - Dùng mảng hoten dùng để lưu danh sách thí sinh: hoten[i] ghi họ và tên thí sinh i. - Với mỗi thí sinh i, tách lấy phần tên lưu vào mảng: ten[i]. - Sắp xếp mảng tên theo thứ tự tăng dần, với mỗi lượt tráo đổi 2 phần tử trong mảng tên thì tráo đổi luôn 2 phần tử tương ứng trong mảng hoten. 37 - Xuất ra kết quả là danh sách thí sinh trong mảng hoten sau khi sắp xếp. Bài 10. SỐ ĐƠN ĐIỆU (Đề thi HSG tỉnh lớp 11 năm học 2013 – 2014) Số a1, a2, …, an được gọi là số đơn điệu nếu ai < ai+1 > ai+2 hoặc ai >
Số có một chữ số; số có hai chữ số khác nhau cũng i= ai+1 < ai+2 (
được gọi là số đơn điệu lần lượt có độ dài bằng 1; 2. Ví dụ: Các số 5, 58, 3748, 32435465768 là số đơn điệu vì: Số 5 có 1 chữ số Số 58 có 2 chữ số khác nhau. Số 3748 có: 3 < 7 > 4 < 8 Số 32435465768 ta thấy: 3 > 2 < 4 > 3 < 5> 4 < 6 > 5 < 7 > 6 < 8 Yêu cầu: Viết chương trình xác định số chữ số lớn nhất tạo thành số đơn điệu
của một số cho trước. Dữ liệu: Vào từ file văn bản SDD.INP: Gồm một số nguyên dương N có không quá 75 chữ số. Kết quả: Ghi ra file văn bản SDD.OUT: Chứa số nguyên là số chữ số lớn nhất tạo thành đoạn số đơn điệu của số N. Ví dụ: SDD.INP SDD.OUT 3748 4 Gợi ý: Số nguyên N có thể có 75 chữ số nên ta không thể xử lý bằng kiểu dữ liệu
số. Ta sẽ đọc số nguyên N vào 1 xâu ký tự và xử lý theo các thao tác xử lý xâu.
Ta đưa bài toán về dạng tìm xâu con dài nhất của xâu tạo thành dãy đơn điệu
(các ký tự trong dãy tăng, giảm đan xen). Ta có thể biểu diễn diễn tính đơn điệu
của một phần tử s[i] bằng biểu thức s[i]-s[i-1]*s[i]-s[i+1] <0. Khi đó yêu cầu của bài toán trở thành tìm độ dài k của xâu con dài nhất
chứa mà mọi phần tử i trong xâu con đều thỏa mãn s[i]-s[i-1]*s[i]-s[i+1] <0 và
lúc đó kết quả cần in ra là k+2. 38 Bài toán yêu cầu tìm xâu con dài nhất nhưng xâu đơn điệu có tính chất:
mọi xâu con của xâu đơn điệu đều đơn điệu nên ta sử dụng phương pháp phát
triển xâu con sẽ tốt hơn phương pháp kiểm tra theo độ dài. Bài 11. CENSOR (Đề thi HSG tỉnh lớp 11 năm học 2015 – 2016) Cho một xâu S có độ dài tối đa là 106 ký tự. Trong xâu S người ta loại bỏ
sự xuất hiện của một xâu con T có độ dài ≤ 100 ký tự. Để làm điều này, người ta
tìm sự xuất hiện của T lần đầu tiên trong S và xóa nó. Sau đó cứ lặp đi lặp lại
quá trình này cho đến khi không còn sự xuất hiện của T trong S. Lưu ý rằng việc
xóa một lần xuất hiện có thể tạo ra một sự xuất hiện mới của T chưa từng tồn tại
trước đó. Hãy xác định nội dung cuối cùng của xâu S. Dữ liệu: Vào từ file văn bản CENSOR.INP: Dòng đầu tiên chứa xâu S. Dòng thứ hai chứa xâu T. Chiều dài của xâu T bé hơn chiều dài của S, và tất cả các kí tự của S và T đều là ký tự thường (trong phạm vi từ a..z). Kết quả: Ghi ra file văn bản CENSOR.OUT chỉ một dòng chứa xâu S sau
khi đã xóa bỏ hết T. Đảm bảo rằng S sẽ không trở nên xâu rỗng trong quá trình
xóa. Ví dụ CENSOR.OUT
whatthefun CENSOR.INP
whatthemomooofun
moo Gợi ý: Ta nếu ta sử dụng lệnh find() kết hợp câu lệnh while để tìm các xâu T
trong xâu S rồi xóa thì kết quả vẫn đúng nhưng sẽ không đảm bảo được thời
gian nên ta sẽ dùng cách sau: - Dùng thêm biến X để chứa kết quả, ban đầu X là xâu rổng; biến ls,lt, lx lần lượt lưu độ dài của xâu S, T, X. - Lần lượt duyệt từng ký tự S[i] của xâu S: + Nối S[i] vào X, nếu lx>=lt thì sao chép lt ký tự cuối của xâu x và
biến tg. + Nếu tg = T thì xóa trong lt ký tự cuối của xâu X. - Sau khi duyệt hết các ký tự của xâu S thì xâu X chứa kết quả cần tìm. Bài 12. ITOA - Chuyển số thành xâu. (http://thptchuyen.ntucoder.net/Problem/Details/7011) Viết chương trình nhập vào các cặp số (a,b). Tính tổng a+b và ghép chúng thành một xâu ký tự. Kiểm tra xem xâu ký tự đó có đối xứng hay không? 39