Tải bản đầy đủ (.docx) (27 trang)

Giúp học sinh phân dạng, tạo dữ liệu đầu vào và cài đặt chương trình tối ưu khi giải một số bài tập về xâu, nhằm nâng cao chất lượng học sinh giỏi môn tin học

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 (251.95 KB, 27 trang )

SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ

TRƯỜNG THPT THỌ XUÂN 5

SÁNG KIẾN KINH NGHIỆM

TÊN ĐỀ TÀI
GIÚP HỌC SINH PHÂN DẠNG, TẠO DỮ LIỆU ĐẦU VÀO VÀ
CÀI ĐẶT CHƯƠNG TRÌNH TỐI ƯU KHI GIẢI MỘT SỐ BÀI
TẬP VỀ XÂU, NHẰM NÂNG CAO CHẤT LƯỢNG HỌC SINH
GIỎI MÔN TIN HỌC.

Người thực hiện: Lê Thị Hạnh
Chức vụ: Giáo viên
SKKN thuộc lĩnh vực (môn): Tin học

THANH HOÁ NĂM 2020



1.1. Lí do chọn đề tài.
Chương trình Tin học 11 THPT hiện nay chủ yếu trang bị kiến
thức và kĩ năng về lập trình cho học sinh. Đây là một nội dung
tương đối khó với đa số học sinh, đòi hỏi các em phải tư duy suy
luận nhiều hơn so với chương trình Tin học lớp 10 và lớp 12. Bên
cạnh đó, Tin học là môn không được chọn để xét tuyển tốt nghiệp,
cao đẳng, đại học nên phần lớn các em ít quan tâm, ít đầu tư về
thời gian cũng như công sức. Tuy nhiên đây là môn học có nội
dung rất bổ ích và thiết thực với các em, không những rèn luyện
tư duy logic mà còn mang tính sáng tạo. giúp cho học sinh có khả
năng phân tích, tổng hợp, trừu tượng hóa, khái quát hóa vấn đề


và đặc biệt là phát triển tư duy. Muốn vậy ngoài dạy đại trà Tin
học trong nhà trường nhằm đảm bảo tính phổ thông, hướng
nghiệp và dạy nghề thì cần phải tạo điều kiện cho những học sinh
có năng khiếu tin học được phát triển về khả năng lập trình và
giải quyết các bài toán. Để đáp ứng yêu cầu này Giáo viên phải có
kiến thức vững vàng, có cách dạy sáng tạo, phù hợp để kích thích
thích thái độ học tập của học sinh, cần phải cung cấp cho học sinh
những kiến thức về thuật toán và các phương pháp thiết kết thuật
toán.
Học sinh THPT là nguồn lao động trẻ có thể sử dụng ngay
sau khi tốt nghiệp do vậy việc được tiếp cận công nghệ thông tin
từ trong nhà trường phổ thông sẽ giúp cho học sinh có thể tự tin
hơn trong công việc. Nhất là những học sinh có niềm đam mê
CNTT và muốn tiếp tục theo đuổi nó thì kiến thức vững vàng về
lập trình từ THPT sẽ giúp các em rất nhiều khi tiếp cận với nhiều
ngôn ngữ lập trình khác nhau, giải quyết vấn đề nhanh hơn, triệt
để hơn. Giữ được thành tích học tập cao hơn các bạn cùng lớp.
Cùng với công tác bồi dưỡng học sinh thi Đại học – Cao đẳng
thì công tác bồi dưỡng học sinh giỏi là một công tác mũi nhọn của
nhà trường. Do đó việc nâng cao chất lượng học sinh giỏi môn Tin
học là cần thiết và cấp bách nhằm góp thêm vào thành tích chung
của nhà trường. Trong quá trình dạy bồi dưỡng học sinh giỏi tôi
gặp rất nhiều bài toán về Xâu. Đây là dạng bài tập khó thường
xuất hiện trong các đề thi học sinh giỏi môn Tin học. Rất nhiều
học sinh khi gặp dạng bài tập này bị mất điểm hoặc điểm không
cao. Nguyên nhân có thể nhiều nhưng trong đó có thể kể đến là:
không nhận diện được dạng bài toán để áp dụng cho đúng thuật
toán phù hợp. Không đọc được dữ liệu đầu vào đối với một số loại
test khó. chương trình cho kết quả output sai hoặc chương trình
cho kết quả output đúng với các bộ input có dữ liệu nhỏ nhưng với

những bộ input có dữ liệu lớn thì chương trình chạy quá thời gian


quy định là 1giây/1test (mặc dù kết quả output vẫn đúng).
Với mong muốn giúp học sinh giải quyết tốt hơn các bài tập
về Xâu và hiểu biết sâu sắc hơn cách giải các bài tập này, tôi
mạnh dạn trình bày sáng kiến kinh nghiệm: “Giúp học sinh
phân dạng, tạo dữ liệu đầu vào và cài đặt chương trình tối
ưu khi giải một số bài tập về xâu, nhằm nâng cao chất
lượng học sinh giỏi môn Tin học.” để trao đổi cùng đồng
nghiệp.
1.2. Mục đích nghiên cứu.
Phân dạng các bài toán về xâu, đưa ra ý tưởng giải quyết, cài
đặt chương trình tối ưu giải quyết một số bài toán cụ thể, qua đó
chỉ ra những sai lầm học sinh thường mắc phải, giới thiệu đến các
em những bài tập từ cơ bản đến khó có thể đưa vào từng dạng để
xử lý.
1.3. Đối tượng nghiên cứu.
+ Học sinh khá giỏi lớp 11 trường THPT Thọ Xuân 5.
+ Một số bài toán về Xâu được nghiên cứu ở nhiều cách làm,
xét trên nhiều phương diện như: độ phức tạp, kết quả output, thời
gian thực hiện chương trình.
1.4. Phương pháp nghiên cứu.
+ Phương pháp nghiên cứu xây dựng cơ sở lý thuyết: Tôi chủ
động tham khảo các tài liệu lấy từ nhiều nguồn nhất là các học
liệu mở trên mạng internet và phân tích có hệ thống các dạng bài
tập theo nội dung đã đề ra.
+ Phương pháp điều tra, khảo sát, thu thập thông tin: Để có
cơ sở cho việc áp dụng phương pháp và kinh nghiệm này, tôi đã
tổ chức điều tra, khảo sát, thu thập thông tin về thực tế dạy học

liên quan đến đề tài của mình ở một số trường trên địa bàn huyện
và các nhóm đội tuyển Tin học hằng năm trong nhà trường.
+ Phương pháp thống kê, xử lý số liệu: Với một bài toán tôi đã
thực hiện nhiều cách khác nhau, dùng phần mềm themis để kiểm
tra output và thời gian thực hiện chương trình.
2. NỘI DUNG CỦA SÁNG KIẾN KINH NGHIỆM
2.1. Cơ sở lí luận của sáng kiến kinh nghiệm.
Nghị quyết hội nghị Trung ương VIII khóa XI đề ra mục tiêu:
“Đối với giáo dục phổ thông tập trung phát triển trí tuệ, thể chất,
hình thành phẩm chất, năng lực công dân, phát hiện và bồi dưỡng
năng khiếu, định hướng nghề nghiệp cho học sinh. Nâng cao chất
lượng giáo dục toàn diện, chú trọng giáo dục lý tưởng truyền
thống đạo đức, lối sống, ngoại ngữ, tin học, năng lực và kỹ năng
thực hành, vận dụng kiến thức vào thực tiễn, phát triển khả năng
sáng tạo và tự học, khuyến khích học tập suốt đời, hoàn thành


đào tạo giáo dục phổ thông giai đoạn sau 2015”.[1]
Căn cứ vào những quan điểm, định hướng trên mục tiêu của
môn Tin học, là phải cung cấp những tri thức cơ bản, làm nền
tảng để học sinh có thể tiếp tục đi sâu vào tìm hiểu và xây dựng
khoa học Tin học hoặc tiếp thu những tri thức của các lĩnh vực kĩ
thuật công nghệ tiên tiến, nhất là các lĩnh vực của công nghệ
thông tin.
2.2. Thực trạng vấn đề trước khi áp dụng sáng kiến kinh
nghiệm.
2.2.1. Về phía Phụ huynh học sinh.
Môn Tin học là môn học không được đưa vào thi tốt nghiệp
hoặc xét các trường Cao đẳng, Đại học. Chính vì vậy đa phần
không được phụ huynh đồng tình khi con mình được lựa chọn vào

đội tuyển Tin học phải đầu tư thời gian để tìm hiểu nó.
2.2.2. Về phía Giáo viên.
Tin học 11 là một lĩnh vực khó truyền tải, Không phải Giáo
viên có chuyên môn tốt sẽ đào tạo được học sinh Giỏi, mà Giáo
viên có chuyên môn tốt phải đồng hành với việc có phương pháp
giảng dạy lập trình tốt. Có sự đánh giá đúng về điểm mạnh, điểm
yếu lập trình của từng học sinh, những sai lầm về lập trình từng
em hay mắc phải.
2.2.3. Về phía học sinh.
Các em thường quen với việc giải toán đó là tìm cách giải sao
cho ra được một đáp án theo đề là được. Chính vì vậy nhiều em đi
thi học sinh giỏi về tự tin là mình làm bài tốt mà không kiểm tra
cách giải của mình đã tối ưu chưa? Đã bao quát được tất cả
trường hợp xảy ra chưa? Đã chạy được test với dữ liệu lớn hay
chưa? Dẫn đến kết quả kỳ thi thấp.
2.2.4. Một số tài liệu hiện có.
Trên thực tế đã có một số tài liệu đề cập đến các bài tập về
Xâu, nhưng các tài liệu này mới chỉ đưa ra thuật toán và chương
trình giải một số bài tập cụ thể làm ví dụ minh họa cho một kỹ
thuật lập trình nào đó khi nghiên cứu mà chưa khái quát dạng.
Các chương trình mà một số tài liệu đưa ra rất khó hiểu và phức
tạp không phù hợp năng lực học sinh Trường THPT Thọ Xuân 5,
chưa bám sát vào cấu trúc thi học sinh giỏi Tỉnh. Khi nghiên cứu


các tài liệu này, không chỉ học sinh mà ngay cả giáo viên còn lúng
túng, mơ hồ, áp dụng một cách máy móc mà chưa biết nên chọn
cách làm nào? Cách làm nào tối ưu hơn?
2.3. Các sáng kiến kinh nghiệm hoặc các giải pháp đã sử
dụng để giải quyết vấn đề.

Từ thực trạng trên, qua 3 năm đứng đội tuyển từ 2016- 2019
khi dạy về kiểu dữ liệu Xâu tôi đã giải quyết như sau:
2.3.1. Phân dạng các bài tập này về những dạng cụ thể để
học sinh có thể dễ nhận diện, áp dụng thuật toán phù hợp.
Dạng 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ụng xâ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.
Các bài tập có thể áp dụng:
Bài 1: Cộng, trừ 2 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 ra tổng và hiệu của 2 số nguyên đó.
* Ý tưởng: Sử dụng xâu để lưu 2 số lớn. Trước hết cho 2
xâu bằng nhau bằng cách chèn thêm nhiều ký tự '0' vào trước xâu
ngắn hơn. Việc thực hiện cộng 2 số sẽ được thực hiện bằng cách
cộng lần lượt các cặp ký tự số tương ứng từ phải sang trái của các
xâu.
* Đoạn chương trình:
function Add(s1,s2:string):string;
var i,nho,z,x,y:longint; s:string;
begin
while length(s1)while length(s2)i:=length(s1); nho:=0; s:='';
while i>=1 do
begin
x:=ord(s1[i]) - ord('0');
y:=ord(s2[i]) - ord('0');
z:=x+y+nho;

s:= chr(z mod 10 + ord('0')) + s;
nho:= z div 10;
dec(i);
end;
Add:=s;
end;


{======Phép trừ ===========}
function sub1(s1,s2:string):string;
var i,nho,z,x,y:longint; s:string;
begin
while length(s1)while length(s2)i:=length(s1); nho:=0; s:='';
while i>=1 do
begin
x:=ord(s1[i]) - ord('0');
y:=ord(s2[i]) - ord('0');
z:=x-y-nho;
if z<0 then
begin
z:=z+10;
nho:=1;
end
else nho:=0;
s:= chr(z + ord('0')) + s;
dec(i);
end;
sub1:=s;

end;
// Với trường hợp số bị trừ nhỏ hơn số trừ ta thực hiện hàm
sau:
function sub(s1,s2:string):string;
begin
if length(s1) > length(s2) then sub:=sub1(s1,s2)
else
if length(s2)>length(s1) then sub:='-'+sub1(s2,s1)
else
if s1>=s2 then sub:=sub1(s1,s2)
else sub:='-'+sub1(s2,s1);
end;
Bài 2 : Số nhỏ nhất (Đề thi học sinh giỏi lớp 11 tỉnh Hà
Tĩnh năm 2008-2009)
Một số nguyên dương n rất lớn có thể được cho bởi P (P ≤
20) số nguyên dương A và P xâu ký tự s1, s2,...,sp (độ dài các xâu
không vượt quá 255) chỉ gồm các số thập phân bằng cách viết s1
liên tiếp A1 lần rồi viết s2 liên tiếp A2 lần,..., viết sp liên tiếp Ap
lần.


Giả sử với số n được cho như trên và cho trước số nguyên
dương k nhỏ hơn số chữ số của N. Hãy tìm cách gạch đi k chữ số
của N để nhận được một số có giá trị nhỏ nhất .[2]
Ví dụ:
Vào
Kết quả
p=3, k =11
44
a1=3, a2 = 4, a3 =

2
s1 = 123, s2=0, s3
= 45
* Ý tưởng : Ở bài toán này N là số nguyên lớn nên ta sử dụng
xâu để biểu diễn nó, giả sử số n lớn được ghép lại bởi m ký tự
khác nhau khi đó sau khi xóa ta còn lại m-k chữ số trong n. Lần
lượt đi tìm m chữ số nhỏ nhất trong xâu còn lại ta được kết quả
cần tìm.
Procedure
xuly;
var m:longint; sm:ansistring; code:integer;
Begin
j:=0;
m:=length(st)-k;
Repeat
sm:='9';
dec(m);
For i:=j+1 to length(st)-m do
If sm>st[i] then
Begin
sm:=st[i];
j:=i;
End;
kq:=kq+sm;
Until m=0;
Val(kq,m,code);
Write(m);
End;
Bài 3: Ghép số lớn ( />Vaxia đã viết được một số lớn trên một cuộn giấy dài và muốn
khoe với anh trai Petia về thành quả vừa đạt được. Tuy nhiên, khi

Vaxia vừa ra khỏi phòng để gọi anh trai thì cô em Kachia chạy vào
phòng và xé rách cuộn giấy thành một số mảnh. Kết quả là trên
mỗi mảnh có một hoặc vài kí số theo thứ tự đã viết. Bây giờ Vaxia
không thể nhớ chính xác mình đã viết số gì. Vaxia chỉ nhớ rằng đó
là một số rất lớn. Để làm hài lòng cậu em trai, Petia quyết định


truy tìm số nào là lớn nhất mà Vaxia đã có thể viết lên cuộn giây
trước khi bị xé. Bạn hãy giúp Petia làm việc này . [2]
Dữ liệu vào:
Ghi một hoặc nhiều dòng. Mỗi dòng ghi một dãy kí số. Số
dòng không vượt quá 100. Mỗi dòng ghi từ 1 đến 100 kí số. Bảo
đảm rằng có ít nhất một dòng mà kí số đầu tiên khác 0.
Dữ liệu ra:
Ghi ra số lớn nhất đã có thể viết trên cuộn giấy trước khi bị
xé rách.
Ví dụ
Inpu Output
t
2
6622000
20 4
004
66
3
3
* Ý 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 phần tử s[i]
đứng trước phần ử s[j] khi (s[i] ghép với s[j]) > (s[j] ghép với s[i]).
Phép cộng này chính là phép ghép hai xâu. Kết quả bài toán là ghi

lần lượt các xâu s[i] đã sắp xếp.
var s: array[0..1000] of string;
i,n,j: word;
procedure qsort(L,H: word);
var tg,k:string;
begin
if l>=h then exit;
i:=l; j:=h;
tg:=s[(l+h) div 2];
repeat
while tg+s[i]while tg+s[j]>s[j]+tg do dec(j);
if i<=j then
begin
if ik:=s[i];
s[i]:=s[j];
s[j]:=k;
end;
inc(i);dec(j);
end;


until i>j;
Qsort(l,j);Qsort(i,h);
end;
begin
s[0]:='0'; n:=0;
while s[n]<>'' do
begin

inc(n);
readln(s[n]);
end;
qsort(1,n-1);
for i:=1 to n-1 do write(s[i]);
readln;
end.
Dạng 2: Tìm số.
Trong dạng 2 này có hai loại bài tập chính:
Loại 1: Xóa đi K số để được số lớn nhất hoặc bé nhất.
* Ý tưởng: Gọi xâu đầu vào là xâu st, lặp K lần mỗi lần xóa
đi 1 kí tự số. Nếu mà st[i] > st[i+1] ( Nếu tìm số bé nhất )thì xóa
kí tự st[i] đi và ngắt. Nếu không có trường hợp nào thỏa mãn thì
xóa đi kí tự cuối cùng của xâu.
Cài đặt thuật toán:
For i:=1 to K do
Begin
Kt:=true;
For j:=1 to length(st)- 1 do
if st[j] > st[j+1] then
Begin Delete(st,j,1); Kt:= false; Break; End;
If kt then delete(st,length(st),1);
End;
Bài toán có thể áp dụng:
Cho một số nguyên dương có N chữ số. Hãy xóa đi K số để số
sau khi xóa là số bé nhất.
Dữ liệu vào: Vào từ file văn bản XOASO.INP gồm
+ Dòng đầu tiên là số nguyên dương có N chữ số (N≤ 10 4).
+ Dòng thứ hai là số nguyên dương K( K< N).
Kết quả: Ghi ra file XOASO.OUT gồm số nguyên bé nhất sau khi

xóa K chữ số.
XOASO.INP
XOASO.OUT
151323343121223 1123331212234
45
5
3


Loại 2: Bỏ đi một số kí tự để được số có K chữ số là số bé
nhất hoặc lớn nhất
* Ý tưởng: Gọi xâu đầu vào là xâu s1, sử dụng vòng lắp
while và vị trí đánh dấu j để duyệt từ đầu xâu đến cuối xâu. Nếu
mà s1[j] < s1[j+1] ( Nếu tìm số lớn nhất ) thì xóa kí tự s1[j] đi và
đưa j lại vị trí đầu tiên, ngược lại thì tăng j lên 1. Kết quả bài toán
là K kí tự đầu trong xâu s1.
Cài đặt thuật toán:
j := 1 ;
while ( length(s1) > 5 ) and ( j <
length(s1) ) do
if s1[j] < s1[j+1] then
begin delete(s1,j,1); j := 1 ; end
else inc(j); s1 := copy(s1,1,5);
Bài toán có thể áp dụng:
Cho trước một xâu kí tự, trong đó có ít nhất 5 chữ số. Hãy
loại bỏ một số kí tự ra khỏi xâu sao cho 5 kí tự cuối cùng còn lại
theo đúng thứ tự tạo thành số lớn nhất.
Dữ liệu vào: Cho tệp Bai1.inp
Kết quả: ghi vào tệp bai1.out
Bai1.inp

Bai1.ou
t
13a7b48cb7d9e68f 89687
7
Dạng 3. Biến
đổi xâu.
Phươ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 hàm, thủ 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 toán có thể áp dụng:
Bài 1. 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 đó .[2]
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

* Ý tưởng: Duyệt từ đầu xâu đến cuối xâu, gặp 2 ký tự liên

tiếp khác giống nhau thì xóa đi một ký tự.
Cài đặt thuật toán:
procedure xuly;
var ch,kt:char; i,max,dem:longint;
begin
assign(f,fo); rewrite(f);
i:=1;
while ibegin if s[i]=s[i+1] then delete(s,i,1)
else inc(i);
end;
Bài 2: Chuẩn hóa Văn bản. (đề thi học sinh giỏi lớp 12 tỉnh
Thanh Hóa năm học 2010-2011).[2]
Một văn bản được gọi là văn bản chuẩn hóa nếu:
- Hai từ liền nhau có duy nhất một dấu cách
- Dấu ngắt câu (dấu chấm, 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 vào phía bên phải của từ cuối cùng
được đóng ngoặc
Hãy viết chương trình kiểm tra và đưa một đoạn văn bản về
dạng chuẩn
Dữ liệu vào: Tệp bai3.inp
Kết quả: Ghi vào tệp bai3.out văn bản đã được chuẩn hóa
Ví dụ:
Bai3.inp
Bai3.out
Thấy rét u tôi bọc lại

Thấy rét u tôi bọc lại
mền
mền
Cô nàng cất rượu ủ thêm
Cô nàng cất rượu ủ
men .
thêm men .
( trích hoa và rượu của - (trích hoa và rượu của Nguyễn Bính)
Nguyễn Bính)
Ý tưởng : Sử dụng thành thạo, linh hoạt các hàm và thủ tục trong
xâu.
while eof(f1)=false do
begin


readln(f1,s) ;
while s[1] = ' ' do delete(s,1,1);
while s[length(s)] = ' ' do delete(s,length(s),1);
while pos(' ',s) <> 0 do delete(s,pos(' ',s),1);
while pos('( ',s) > 0 do delete (s,pos('( ',s)+1,1);
while pos(' )',s) <> 0 do delete (s,pos(' )',s),1);
for i:= 1 to 6 do
begin
st := ' '+ a[i] ;
while pos(st,s) <> 0 do
delete(s,pos(st,s),1);
while (pos(a[i],s) > 0) and (pos(a[i],s) < length(s)) and
(s[pos(a[i],s)+1] <> ' ') do
insert(' ',s,pos(a[i],s)+1);
end;

Dạng 4: Tần suất xuất hiện.
Phương pháp chung: Với dạng bài tập này ta nên sử dụng thuật
toán đếm phân phối
Bài 1: Kí tự khác nhau ( Đề thi HSG Tỉnh Thanh Hóa năm
2015-2016).[2]
Cho xâu S chỉ gồm các kí tự là chữ cái tiếng anh và các chữ
số (có phân biệt chữ in hoa, in thường).
Yêu cầu: Hãy xác định số kí tự khác nhau trong xâu S và mỗi kí
tự xuất hiện bao nhiêu lần.
Dữ liệu vào: Vào từ file văn bản BAI2.INP gồm 1 dòng duy nhất
là xâu kí tự S (có độ dài không quá 255).
Kết quả: Kết quả ghi ra file văn bản BAI2.OUT gồm:
- Dòng đầu ghi số kí tự khác nhau.
- Các dòng tiếp theo, mỗi dòng ghi một kí tự xuất hiện trong
xâu S và số lần xuất hiện của nó. Các kí tự đưa ra theo thứ tự chữ
cái in hoa, in thường, chữ số. Các chữ cái, chữ số đưa ra theo thứ
tự từ điển.
Ví dụ:
BAI2.INP
AzB1C9A1BC

BAI2.OUT
6
A2
B2
C2
z1
12
91



* Ý tưởng:
- Với xâu có độ dài tối đa 106 ta sẽ sử dụng khai báo kiểu
xâu Ansistring
- Sử dụng mảng đánh dấu B['a'...'z'] of longint để đếm số
lần xuất hiện các ký tự trong xâu s với B[ch] = d có nghĩa là ký tự
ch xuất hiện d lần.
- Lần theo các giá trị của mảng B 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 không trong mảng
B) và tìm giá trị lớn nhất của mảng B ta sẽ tìm được ký tự xuất
hiện nhiều lần nhất.
Cài đặt thuật toán:
procedure xuly;
var ch,kt:char; i,max,dem:longint;
begin
or ch:='a' to 'z' do b[ch]:=0;
for i:=1 to length(s) do inc(b[s[i]]);
dem:=0; max:=0;
for ch:='a' to 'z' do
begin
if b[ch]<>0 then inc(dem);
if b[ch]>max then
begin max:=b[ch]; kt:=ch;
end;
end;
writeln(dem, ' ', max);
end;
Bài 2: Mã hóa xâu ( Đề thi khảo sát HSG trường THPT Thọ
Xuân 5)
Bình đang tìm hiểu một trong những kĩ thuật mật mã hóa đơn

giản nhất. Với bản tin cần được mã hóa, phương pháp này được sẽ
mã hóa thành một xâu với quy tắc như sau:
- Xâu mã hóa chỉ lưu lại các kí tự chữ cái xuất hiện đầu tiên.
Nói cách khác, các kí tự nào xuất hiện lớn hơn một lần trở
lên, sẽ bị xóa bỏ, chỉ giữ lại kí tự đầu tiên.
- Giá trị mật mã của xâu được tính bằng tổng số lần xuất hiện
của các kí tự có tần suất xuất hiện lớn hơn một lần.
Các bạn hãy cùng Bình giải quyết bài toán này nhé!
Dữ liệu vào: Vào từ tệp BAI2.INP
Một dòng gồm nhiều chuỗi các kí tự, có tổng độ dài không vượt
quá 106.
(Các kí tự là chữ cái in hoa hoặc chữ cái thường.)
Dữ liệu ra: ghi trên một dòng số các giá trị mật mã của xâu và
xâu đó sau khi được mã hóa vào tệp BAI2.OUT


BAI2.INP
MOI CAC BAN GHE
THAM THO XUAN NAM
LAN NUA NHE

BAI2.OUT
30 moicabnghetxul

Ý tưởng: sử dụng thuật toán đếm phân phối, tìm tần suất xuất
hiện của các kí tự, kí tự nào xuất hiện > 1 lần trở lên, sẽ bị xóa bỏ,
chỉ giữ lại kí tự đầu tiên, tần suất > 1 lần.
Lưu ý: Chuyển đổi dữ liệu đầu vào đồng nhất thành chữ thường,
kiểm soát khoảng trắng trong xâu.
Cài đặt thuật toán:

procedure xuli;
var
i,j,res:data;
c:char;
begin
res:=0;
fillchar(dd,sizeof(dd),0);
s:=upcase(s);
for i:=1 to length(s) do
if s[i] in ['A'..'Z'] then s[i]:=chr(ord(s[i])+32);
for i:=1 to length(s) do
if s[i]<>' ' then inc(dd[s[i]]);
res:=0;
for c:='A' to 'z' do
if dd[c]>1 then inc(res,dd[c]);
write(f2,res,' ');
fillchar(dd,sizeof(dd),0);
for i:=1 to length(s) do
if (s[i]<>' ') and (dd[s[i]]=0) then
begin dd[s[i]]:=1; write(f2,s[i]); end;
Dạng 5. Xâu 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ải sang trái thì xâu đó được gọi là xâu
Palinhdrome.
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ất Palindrome 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ột xâ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.
Xâu Palindrome 1
Cho một xâu S có độ dài không vượt quá 10 6. Kiểm tra xem
xâu S có phải là xâu Palindrome hay không?
* Ý tưởng: Một xâu s có tính chất đối xứng khi s[i] = s[ni+1] với i chạy từ 1 đến length(s) div 2. Dựa trên cơ sở đó ta xây
dựng hàm kiểm tra.
* Chương trình tham khảo
Var s:ansitring
function palindrome(s: string): boolean;
var i, n : integer;
begin
n := length(s);
for i := 1 to (n div 2) do
if s[i] <> s[n+1-i] then begin palindrome := false;
exit; end;
palindrome := true;
end;
begin
write('nhap s:'); readln(s);
If palindrome(s) then write('xau doi xung') else write('xau khong
doi xung');
end.
Bài tập có thể áp dụng:
Bài 1: Một xâu kí tự được gọi là xâu Palindrome ( đối xứng ) nếu
ta đọc từ trái sang phải hay đọc từ phải sang trái đều giống nhau.(
Đề thi HSG Tỉnh thanh hóa năm 2012-2013) .[2]
Yêu cầu: Cho trước một xâu kí tự S. Hãy xác định số xâu đối xứng
là xâu con của nó. Một kí tự cũng được coi là một xâu đối xứng.
Xâu con của S là xâu gồm một số kí tự liên tiếp trong S.
Dữ liệu vào: Từ tệp văn bản

BAI2.INP:
Dòng thứ nhất ghi số nguyên dương N (N<100).
N dòng tiếp theo mỗi dòng là một xâu kí tự ( độ dài xâu
<255).
Kết quả: Ghi vào tệp văn bản BAI2.OUT gồm:
N dòng, mỗi dòng chứa một số nguyên biểu thị số xâu
con đối xứng.
BAI2.INP
1
IOI

BAI2.OUT
4


Xâu con Palindrome 2
Cho một xâu S có độ dài không vượt quá 1000 kí tự; tìm
xâu palindrome dài nhất là xâu con của S.
* Ý tưởng: Sử dụng phương pháp quy hoạch động bằng
cách sử dụng mảng 2 chiều F và giá trị F[i, j] = true/false nếu
đoạn gồm các kí tự từ i đến j của S có/không là palindrome.
Ta có công thức là:
F[i, i]:=True ;F[i, j]:=F[i+1, j-1];(nếu s[i] = s[j] ); F[i, j]:= False;
( nếu s[i] <> s[j] )
* Đoạn chương trình tham khảo
var
s: ansistring; n,i,j,d,max,k,csd,csc:longint;
F: array[0..1001,0..1001] of boolean;
begin
write('nhap s:'); readln(s);

FillChar( F, sizeof(F), false );
n:=length(s); max:=1;
for i := 1 to n do F[i, i] := True;
for k := 1 to (n-1) do
for i := 1 to (n-k) do
begin
j := i + k;
F[i, j] := ( F[i+1, j-1] ) and (s[i] = s[j] );
end;
for i:=1 to n do
for j:=1 to n do
begin
d:=j-i+1;
if (f[i,j]=true) and (d>max) then
begin
max:=d;
csd:=i;
csc:=j;
end;
end;
for i:=csd to csc do write(s[i]);
readln;
end.
Bài tập có thể áp dụng:
Xâu ký tự X được gọi là xâu con của ký tự Y nếu ta có thể xóa
đi một số ký tự trong xâu Y để được xâu X. Cho biết hai xâu ký tự
A và B, hãy tìm xâu ký tự C có độ dài lớn nhất và là con của của
cả A và B.
Dữ liệu: Vào từ file bai1.inp gồm
+ Dòng 1: Chứa xâu A( độ dài xâu ≤ 103).



+ Dòng 2: Chứa xâu B( độ dài xâu ≤ 103).
Kết quả: Ghi ra file bai1.out một dòng ghi độ dài xâu C tìm được.
Bai1.inp
Bai1.out
Abc1def2ghi3
10
Abcdefghi123
Dạng 6: Tìm xâu con.
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 đầu vào nhỏ, tuy nhiên nên sử dụng
linh hoạt các phương pháp khác như phương pháp quy hoạch
động trong trường hợp bài toán có bộ dữ liệu lớn.
Bài tập có thể áp dụng:
Bài 1. Đếm xâu con
Cho xâu s (có độ dài không vượt quá 103) chỉ gồm các ký tự
từ 'a' đến 'z'. Đếm số lượng xâu con liên tiếp khác nhau nhận được
từ xâu s.
Ví dụ: S = 'abab' có 7 xâu con là: a, b, ab, ba, aba,bab,abab
* Ý tưởng: Lưu các xâu con có độ dài i (với i từ 1 đến
length(s)) vào một mảng, sau đó sắp xếp mảng tăng dần rồi thực
hiện đếm số lượng các xâu con khác nhau ta được số lượng xâu
con có độ dài i.
procedure xuly;
var kq:longint;
begin
write('nhap xau s ');readln(s);
kq:=0;

for i:=1 to length(s) do
begin
d:=1;
for j:=i to length(s) do
begin a[d]:=copy(s,j-i+1,i); inc(d);
end;
Q_sort(1,d-1); a[d+1]:=' ';
for t:=1 to d-1 do
if a[t]<>a[t+1] then inc(kq);
end;
write(kq);
end;
Bài 2: Xâu con ( Đề thi học sinh giỏi lớp 12 tỉnh nghê an năm
học 2008-2009) .[2]
Cho trước hai xâu ký tự s1 và s2. Viết chương trình tính số lần lặp
lại của xâu s1 trong xâu s2.
Dữ liệu vào: Từ tệp xau.inp gồm :


- Dòng đầu chứ s1.
- Dòng thứ hai chứa xâu s2.
Kết quả: Ghi ra tệp xau.out một dòng duy nhất ghi số lần lặp lại
của xâu s1 trong xâu s2.
XAU.INP
XAU.OUT
aba
4
bababababa
* Ý tưởng: Sử dụng hàm Pos(s1,s2) để xác định có hay không
xuất hiện xâu s1 trong xâu s2. Giả sử giá trị hàm trả về là i khác

0, ta tăng biến đếm lên 1 và xóa ký tự thứ i trong xâu s2, tiếp tục
quá trình trên cho đến khi hoặc i=0 hoặc xâu s2 rổng.
Cài đặt thuật toán:
dem:=0;
while (pos(s1,s2)<>0) and (length(s2)<>0) do
begin
inc(dem);
delete(s2,1, pos(s1,s2));
end;
*
Lưu
ý:
delete(s2,1,pos(s1,s2))
chứ
không
phải
delete(s2,pos(s1,s2),1) vì nếu dùng delete(s2,pos(s1,s2),1) gặp
trường hợp sau khi xóa xong sẽ tạo với kí tự phía trước thành một
lần lặp nữa.
Ví dụ: nếu dung delete(s2,pos(s1,s2),1)=> output sai.
XAU.INP
XAU.OUT
aba
5
aababababa
Bài 3. Chiếc nón kỳ diệu (Đề thi học sinh giỏi lớp 12 tỉnh Phú
Yên năm học 2009-2010) .[2]
Một lần trong chương trình “Chiếc nón diệu kỳ”, ở phần chơi
dành cho khán giả, thay vì đoán chữ như mọi khi, người dẫn
chương trình tự mình quay “chiếc nón” và cho hiện lên màn hình

trước mặt khán giả trong trường quay các số trong các ô mà kim
chỉ thị lần lượt đi qua. “Chiếc nón” quay đúng một số nguyên
vòng, nên trong dãy số hiện lên màn hình, số cuối cùng trùng với
số đầu tiên. Sau đó, người dẫn chương trình mời một khán giả ở
cuối trường quay (chỉ nhìn thấy màn hình mà không nhìn thấy
“chiếc nón”) cho biết chiếc nón có tối thiểu bao nhiêu ô?
Yêu cầu: Hãy trả lời câu hỏi của người dẫn chương trình.
Dữ liệu: Vào từ tập tin văn bản CNDK.INP gồm hai dòng:
+ Dòng 1 ghi số N là số lượng số đã hiện lên màn hình,
(2 ≤ N≤ 100).


+ Dòng 2 ghi lần lượt N số, mỗi số có giá trị không quá
32000.
Kết quả: Ghi ra tập tin văn bản CNDK.OUT số ô tối thiểu của
“chiếc nón”.
Lưu ý: Các số trên cùng một dòng cách nhau ít nhất một khoảng
trắng.
Ví dụ:
CNDK.INP
CNDK.OUT
13
6
5313525313525
* Ý tưởng: Nhận thấy nếu ghép toàn bộ các số hiện lên
màn hình (trừ số cuối cùng) vào một xâu S thì trong xâu S sẽ luôn
tồn tại một xâu s1 dài nhất mà khi ghép liên tiếp một số lần xâu
s1 ta sẽ được xâu s. Số lần xuất hiện xâu s1 là kết quả cần tìm.
Bài toán trở thành tìm xâu con dài nhất s1.
Cài đặt thuật toán:

s:='';
for i:=1 to n do
begin read(f,x); str(x,s1); s:=s+s1; end;
dem:=0;
delete(s,length(s),1);
for i:=1 to length(s) do
begin
s2:=s; s1:=copy(s2,1,i);
while (pos(s1,s2)<>0) and (length(s2)<>0) do delete(s2,1,i);
if length(s2)=0 then
begin dem:=i; write(dem); break; end;
end;
Dạng 7: Tách từ, sắp xếp xâu.
Phương pháp chung: dựa vào tính chất của từ trong một xâu
( các từ được phân cách nhau bằng dấu cách ) ta sử dụng hàm
pos(‘ ‘,s2) để tách các từ trong xâu, sau đó sử dụng thuật toán
sắp xếp quick sort để sắp xếp các từ trong xâu.
Cài đặt thuật toán tách từ:
procedure tachtu;
var x,tu:ansistring; dem:longint;
begin
n:=length(s); x:=s; dem:=0;
while (pos(' ',x)<>0) and (length(x)>=0) do
begin i:=pos(' ',x); tu:=copy(x,1,i); inc(dem); a[dem]:=tu;
delete(x,1,i); end;


Bài toán có thể áp dụng:
Bài 1. Sắp xếp xâu (Đề thi học sinh giỏi lớp 12 tỉnh Quảng Bình
năm học 2012-2013) .[2]

Người ta định nghĩa: Từ là một nhóm ký tự đứng liền nhau.
Cho một xâu St gồm các ký tự lấy từ tập ‘a’ .. ‘z’ và dấu
cách. Xâu không quá 20 từ, mỗi từ dài không quá 10 ký tự.
Yêu cầu: Sắp xếp các từ của xâu ký tự theo thứ tự không giảm
của độ dài các từ trong xâu St.
Dữ liệu vào: Cho trong file văn bản SAPXAU.INP, có cấu trúc:
- Dòng 1: Ghi một xâu ký tự St (có ít nhất 1 từ).
Dữ liệu ra: Ghi ra file văn bản SAPXAU.OUT, theo cấu trúc:
- Dòng 1: Ghi các từ của xâu ký tự sau khi được sắp xếp. Các từ
được ghi cách nhau đúng một dấu cách.
Ví dụ:
SAPXAU.INP
SAPXAU.OUT
acb abcde
acb abc abcd
abcd abc
abcde
Bài 2. Sắp xếp xâu (Đề thi học sinh giỏi lớp 11 tỉnh Quảng Bình
năm học 2011-2012) Mỗi xâu kí tự St được lấy từ tập các ký tự
’a’...’z’, ’0’...’9’ và có độ dài tối đa là 1000 kí tự. Cho N xâu kí tự St
(0 < N ≤ 200).
Yêu cầu: Thực hiện sắp xếp N xâu kí tự St theo thứ thự
không giảm của số lượng các kí tự chữ số có trong mỗi xâu St.
Dữ liệu vào: Cho trong file văn bản SAPXEP.INP có cấu trúc như
sau:
- Dòng 1: Ghi số nguyên N.
- N dòng tiếp theo: Mỗi dòng ghi một xâu St.
Dữ liệu ra: Ghi ra file văn bản SAPXEP.OUT theo cấu trúc như
sau:
- Ghi N dòng: Mỗi dòng ghi một xâu St, các xâu được ghi theo thứ

tự đã sắp xếp.
SAPXEP.OU
SAPXEP.INP T
3
cb1
abc1x2y3z 1cd7hd
cb1
abc1x2y3z
1cd7hd
2.3.2. Tạo test dữ liệu đầu vào kiểu xâu.
Hiện nay không có phần mềm nào để tạo ra test. Mà chúng
ta tạo ra test thông qua code đúng: khi đưa input vào thì phải cho


ra output đúng đắn (không cần về mặt thời gian). Khi chúng ta đã
có code đúng thì công việc còn lại là tạo ra được các file input. Để
tạo ra được file input tốt thì các file input đó phải quét hết được
các trường hợp của bài toán. Để tạo file input cho kiểu dữ liệu xâu
chúng ta có thể sử dụng:
+ Bằng tay: gõ trực tiếp dữ liệu từ bàn phím vào
+ Dùng chương trình để sinh ra các file input. Thông thường
thì dùng chương trình để sinh ra các file input có dữ liệu đặc biệt
và ngẫu nhiên. Đối với sinh dữ liệu ngẫu nhiên thì ta chú ý các
hàm và thủ tục : randomize; random(n); chr(n); ord(ch);
+ Tạo ra file input bai1.inp gồm dòng đầu là số nguyên
dương N (N ≤ 106), dòng thứ hai là một xâu ký tự ngẫu
nhiên độ dài N gồm các chữ cái từ ‘a’ đến ‘z’.
const fo='bai1.inp';
maxn=round(1e6);
var i,n: longint;

BEGIN
randomize;
assign(output,fo); rewrite(output);
n:= random(maxn)+1;writeln(n);
for i:= 1 to n do
write(chr(ord('a')+ random(ord('z')-ord('a')+1)));
close(output);
END.
+ Tạo ra file input bai1.inp gồm dòng đầu là số
nguyên dương N (N ≤ 106), dòng thứ hai là một xâu ký tự
ngẫu nhiên độ dài N gồm các chữ cái từ latin.
const fo='bai1.inp';
maxn=round(1e6);
var i,j,n: longint;
ch: char;
a: array[1..255] of char;
BEGIN
randomize;
assign(output,fo); rewrite(output); n:= random(maxn)
+1;writeln(n);
i:=0;
for ch:='a' to 'z' do
begin
inc(i); a[i]:=ch;
end;
for ch:= 'A' to 'Z' do
begin inc(i); a[i]:=ch;
end;
for j:=1 to n do



write(a[random(i)+1]);
close(output);
END.
+ Tạo ra file input bai1.inp gồm dòng đầu là số
nguyên dương K (K≤ 104), K dòng tiếp theo là một xâu ký
tự ngẫu nhiên độ dài N gồm các chữ cái từ ‘a’ đến ‘z’.
const fo='MANGXAU.inp';
MAXK=ROUND(10000);
maxn=round(10000);
var i,n,K,J: longint;
BEGIN
randomize;
assign(output,fo); rewrite(output);
n:= random(maxn)+1;K:=RANDOM(maxk)+1;writeln(K);
for j:=1 to k do
BEGIN
for i:= 1 to n do
write(chr(ord('a')+ random(ord('z')-ord('a')+1)));
WRITELN;
END;
close(output);
END.
+ Tạo ra file input bai1.inp gồm dòng đầu là số
nguyên dương K (K≤ 104), K dòng tiếp theo là một xâu ký
tự ngẫu nhiên độ dài N gồm các chữ cái latin
const fo='taoxau_inhoa_inthuong.inp';
maxk=1000;
maxn=round(1000);
var g,i,j,n,k: longint;

ch: char;
a: array[1..255] of char;
BEGIN
randomize;
assign(output,fo); rewrite(output);
n:= random(maxn)+1; k:=random(maxk)+1;writeln(k);
i:=0;
for ch:='a' to 'z' do begin inc(i);a[i]:=ch; end;
for ch:= 'A' to 'Z' do begin inc(i);a[i]:=ch; end;
i:=n;
for j:=1 to maxk do
begin
for g:=1 to n do


write(a[random(g)+1]);
writeln;
end;
close(output);
END.
2.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.
Qua các lần thi khảo sát tại trường và liên trường chất lượng
học sinh giỏi được nâng lên, các bài tập về xâu các em lấy điểm
gần như trọn vẹn mặc dù chất lượng đề có độ khó tăng dần.
Kết quả điểm thi học sinh giỏi cấp tỉnh năm 2018 - 2019 môn
Tin học THPT của học sinh trường tôi có sự tiến bộ rõ rệt: 2 em
tham gia thi đạt giải cả 2 em với 1 giải ba, 1 giải khuyến khích
(trong khi những năm học trước không có học sinh nào có giải).
Kết quả HSG năm 2016 -2017

STT
HỌ TÊN
ĐIỂM
1
Lê Văn Thọ
7/20
Kết quả HSG năm 2017 -2018
STT
HỌ TÊN
ĐIỂM
1
Lê Văn Bình
8/20
2
Lê Văn Trà
10/20
Kết quả HSG năm 2018 -2019
STT
HỌ TÊN
ĐIỂM
1
Lê Văn Bình
15/20
2
Lê Văn Trà
14/20
3. Kết luận, kiến nghị.
3.1. Kết luận.
Bài tập về kiểu dữ xâu rất nhiều và đa dạng, nhưng trong
sáng kiến kinh nghiệm trên tôi đã chia các bài tập thành các dạng

cụ thể (chỉ là một số dạng thường gặp). Đối với mỗi dạng tôi đã
xây dựng nhiều cách giải sau đó sử dụng phần mềm themis để đo
thời gian và độ phức tạp để cuối cùng giới thiệu đên các đồng
nghiệp cách giải tối ưu cho từng dạng.
Đề tài này là kinh nghiệm mà bản thân tôi đúc rút trong quá trình
thực hiện nhiệm vụ giảng dạy đội tuyển tại trường THPT Thọ Xuân
5. Tôi nhận thấy khi áp dụng đề tài, có nhiều chuyển biến tích cực
về hiệu quả và chất lượng giảng dạy đội tuyển . Đề tài là một gợi
ý thú vị, là tài liệu tham khảo cho các đồng nghiệp trẻ chưa có
nhiều kinh nghiệm trong công tác bồi dưỡng học sinh giỏi. Vì vậy,
tôi mạnh dạn trình bày cùng đồng nghiệp để được trao đổi, rút
kinh nghiệm, mong nhận được sự đóng góp để hoàn thiện kinh
nghiệm giảng dạy cho bản thân.


3.2. Kiến nghị.
Để sáng kiến kinh nghiệm này áp dụng mang lại hiệu quả tốt
nhất, bản thân tôi đề xuất với Ban chuyên môn trường THPT Thọ
Xuân 5 ngoài những đợt thi khảo sát chất lượng đội tuyển liên
trường tạo thêm các đợt giao lưu học hỏi theo chuyên đề. Đề xuất
với Sở giáo dục tạo thêm những đợt bồi dưỡng chuyên môn
nghiệp vụ giảng dạy đội tuyển học sinh giỏi.
XÁC NHẬN CỦA THỦ TRƯỞNG Thanh Hóa, ngày 14 tháng 7
ĐƠN VỊ
năm 2020
Tôi xin cam đoan đây là
SKKN của mình viết, không
sao chép nội dung của người
khác.


Lê Thị Hạnh


×