Tải bản đầy đủ (.doc) (29 trang)

Sáng kiến kinh nghiệm kiểu xâu bồi dưỡng HSG 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 (227.09 KB, 29 trang )

 Sáng kiến kinh nghiệm

A. PHẦN MỞ ĐẦU
1. Lí do chọn đề tài
Trong Pascal cũng như các NNLT khác, dữ liệu trong bài toán không chỉ là
dữ liệu kiểu số mà còn có kiểu dữ liệu phi số. Kiểu xâu là một trong các kiểu dữ
liệu được giới thiệu trong sách giáo khoa tin học 11. Tuy nhiên, thời lượng chỉ có
2 tiết nên học sinh chưa được tìm hiểu sâu và làm nhiều bài tập về kiểu dữ liệu
này. Mặt khác, trong thực tế có nhiều bài toán chỉ có thể dùng kiểu xâu mới giải
quyết được. Không những thế trong các đề thi học sinh giỏi lớp 11 và 12 có nhiều
bài toán liên quan đến việc sử dụng kiểu dữ liệu xâu. Để giải quyết được những bài
toán này không những đòi hỏi học sinh phải có kiến thức cơ bản về xâu mà còn
phải nắm bắt được và vận dụng linh hoạt các thao tác xử lí xâu và một số thuật
toán phức tạp khác.
Tôi chọn đề tài “Đi sâu tìm hiểu các dạng bài toán kiểu xâu” với mong muốn
giúp học sinh có thêm tài liệu để có thể hiểu rõ, sâu hơn về kiểu dữ liệu xâu.
2. Mục đích nghiên cứu
Giúp học sinh nắm được các kiến thức về kiểu xâu từ đó giải được các bài
tập cơ bản và nâng cao về nó
3. Nhiệm vụ nghiên cứu
• Tìm hiểu các kiến thức về kiểu dữ liệu xâu
• Đưa ra được các dạng bài tập về kiểu dữ liệu xâu và giải quyết nó
4. Phạm vi nghiên cứu
• Cách khai báo dữ liệu kiểu xâu
• Các thao tác xử lí xâu
• Một số bài tập cơ bản về xâu
• Các bài tập nâng cao được chon lọc.
5. Phương pháp nghiên cứu
• Phương pháp nghiên cứu lý thuyết: nghiên cứu sách, báo và các tài liệu điện
tử.
• Phương pháp phỏng vấn chuyên gia: tiếp thu ý kiến cố vấn, đánh giá của


các giáo viên có kinh nghiệm.

1


 Sáng kiến kinh nghiệm

• Tham khảo ý kiến của đồng nghiệp.
6. Nội dung
Chương 1: Các kiến thức cơ bản về kiểu xâu
Tìm hiểu cách khai báo và các thao tác xử lí xâu
Chương 2: Một số dạng bài tập về kiểu xâu
Giải quyết một số bài tập kiểu xâu (theo dạng) thường gặp

2


 Sáng kiến kinh nghiệm

B. PHẦN NỘI DUNG
CHƯƠNG I: CÁC KIẾN THỨC CƠ BẢN VỀ KIỂU XÂU
1.1. Khái niệm
- Xâu: Là dãy các kí tự trong bộ mã ASCII, mỗi kí tự là một phần tử của xâu
- Độ dài xâu: Số lượng kí tự trong xâu được gọi là độ dài xâu
- Xâu rỗng: Xâu có độ dài bằng 0 gọi là xâu rỗng
1.2. Khái báo
- Gián tiếp:
Type <tên kiểu xâu> = string[độ dài lớn nhất của xâu];
Var <tên biến xâu> : <tên kiểu xâu>;
- Trực tiếp:

Var <tên biến xâu> : string[độ dài lớn nhất của xâu];
1.3. Nhập, xuất dữ liệu kiểu xâu
- Nhập, xuất biến xâu:
Có thể sử dụng các thủ tục xuất nhập Write, Writeln, Read, Readln để xuất,
nhập các biến kiểu String.
- Truy cập đến từng phần tử của xâu: <tên biến xâu>[chỉ số]
1.4. Các thao tác xử lí xâu
- Phép ghép xâu
• Kí hiệu: dấu cộng (+)
• Ý nghĩa: ghép nhiều xâu thành một xâu
- Các phép so sánh
• Các phép so sánh: = , < >, >, <, >=, <=
• Quy tắc so sánh:
 Xâu A lớn hơn xâu B nếu kí tự đầu tiên khác nhau giữa chúng kể từ trái
sang trong xâu A có mã ASCII lớn hơn
 Nêu A và B là các xâu có độ dài khác nhau và A là đoạn đầu của B thì A
là nhỏ hơn B
3


 Sáng kiến kinh nghiệm

- Thủ tục delete(st,vt,n) Thực hiên việc xóa n kí tự của biến xâu st, bắt đầu từ vị trí
vt
- Thủ tục insert(s1,s2,vt) chèn xâu s1 vào xâu s2 bắt đầu ở vị trí vt
- Thủ tục str(num, st) đổi số nguyên hay thực num thành dạng xâu ký tự, kết quả
lưu vào biến st.
- Thủ tục val(st:string, num, code) đổi xâu số st thành số và gán kết quả lưu vào
biến num. Nếu việc chuyển đổi thành công thì biến code có giá trị là 0, ngược
lại biến code có giá trị khác 0 (vị trí của lỗi).

- Ham copy(s,vt,n) tạo xâu gồm n kí tự liên tiếp bắt đầu từ vị trí vt của xâu s
- Hàm length(s) cho giá trị là độ dài xâu s
- Hàm pos(s1,s2) cho vị trí xuất hiện đầu tiên của xâu s1 trong xâu s2
- Hàm upcase(ch) cho chữ cái in hoa ứng với chữ cái ch
- Hàm chr(x) cho giá trị là kí tự có mã ASCII thập phân bằng x
- Hàm ord(ch) cho giá trị mã ASCII thập phân của kí tự ch

4


 Sáng kiến kinh nghiệm

CHƯƠNG II: MỘT SỐ DẠNG BÀI TẬP VỀ KIỂU XÂU
DẠNG 1: MÃ HÓA XÂU
BT1: Mã hóa Xê Da
Để 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 mỗi chữ cái bằng
chữ cái đứng sau 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 thứ N, sau chữ cái N là chữ cái thứ nhất,… Cách mã hóa này được
gọi là mã Xê Da. Các kí tự ngoài bảng chữ cái vẫn được giữ nguyên.
Cho tệp văn bản XEDA.INP có cấu trúc như sau:
-

Dòng 1: ghi số nguyên K (1
-

Dòng 2: Xâu S1


-

Dòng 3: Xâu S2

Các xâu S1, S2 không quá 255 kí tự
Hãy lập trình đọc dữ liệu từ tệp trên, thực hiện mã hóa xâu S1 theo quy tắc Xê Da
và giải mã xâu S2 (S2 là xâu đã được mã hóa theo quy tắc Xê Da). Kết quả ghi vào
tệp XEDA.OUT
Ví dụ
XEDA.INP

XEDA.OUT

3

VDQT NLHQ NLQK QJKLHP

Sang kien kinh nghiem

TIN HOC 12

Wlq krf 12
Ý tưởng:
- Viết chương trình con mã hóa 1 kí tự từ đó thực hiện mã hóa cả xâu kí tự
- Viết chương trình con giải mã 1 kí tự từ đó giải mã cả xâu kí tự
Chương trình:
var S1,S2,S,sg:string;
g:text;
k:integer;


5


 Sáng kiến kinh nghiệm
procedure doc_dl;
var f:text;
begin
assign(f,'xeda.inp');
reset(f);
readln(f,k);
readln(f,s1);
read(f,s2);
close(f);
end;
function mahoa(x : char) : char;
var vtri : byte;
begin
if upcase(x) in ['A'..'Z'] then
begin
vtri := ord(upcase(x))-ord('A');
vtri := vtri+k;
mahoa := char( vtri mod 26+ord('A'));
end
else mahoa := x;
end;
function giaima(x : char) : char;
var vtri : byte;
begin
if upcase(x) in ['A'..'Z'] then

begin
vtri := ord(upcase(x))-ord('A');
vtri := vtri-k+26;
giaima := char( vtri mod 26 + ord('A'));
end
else giaima := x;
end;
procedure mahoatu(s1 : string);
var
i
: byte;
begin
S:='';
for i := 1 to length(s1) do S:=S+mahoa(S1[i]);
end;
procedure giaimatu(s2 : string);
var
i
: byte;
begin
SG:='';
for i := 1 to length(s2) do Sg:=Sg+giaima(s2[i]);
end;
BEGIN
assign(g,'xeda.out');
rewrite(g);
doc_dl;
mahoatu(S1);
writeln(g,S);
giaimatu(s2);

writeln(g,Sg);
close(g);
END.

BT2 Mã hoá theo khoá

6


 Sáng kiến kinh nghiệm

Cho trước khoá là một hoán vị của n số (1, 2, ..., n). Khi đó để mã hoá một xâu kí
tự ta có thể chia xâu thành từng nhóm n kí tự (riêng nếu nhóm cuối cùng không đủ
n kí tự thì ta có thể thêm các dấu cách vào sau cho đủ) rồi hoán vị các kí tự trong
từng nhóm. Sau đó, ghép lại theo thứ tự các nhóm ta được một xâu đã mã hoá.
Dữ liệu vào được cho bởi tệp MHKHOA.INP gồm 3 dòng
- Dòng 1: xâu kí tự S
- Dòng 2: số n
- Dòng 3: là một hoán vị của n
Hãy viết chương trình mã hoá một xâu kí tự S, xâu sau khi mã hóa ghi vào tệp
MHKHOA.OUT
Ví dụ:
MHKHOA.INP
MHKHOA.OUT
english
gnlehs i
4
3241
Ý tưởng:
- Đọc hoán vị vào mảng

- Cần thực hiện hoán vị length(s) div n (từ 0 đến length(s) div n -1) đoạn, với mỗi
đoạn ta thực hiện hoán vị n kí tự
Chương trình:
Var n,x,code,i:Integer;
S,KQ:String;
ch:char;
g:text;
a:array[1..256] of integer;
Procedure Doc_dl;
Var f:text;
Begin
assign(f,'mhkhoa.inp');
reset(f);
readln(f,S);
readln(f,n);
while not eoln(f) do
begin
read(f,ch);
val(ch,x,code);
i:=i+1;
a[i]:=x;
end;
close(f);
End;
Procedure Xu_ly;
Var i,j:Integer;
Begin
if (Length(S) Mod n) <>0 then
For i:=1 to n-(Length(S) Mod n) do S:=S+' ';
KQ:='';

For i:=0 to (Length(S) Div n)-1 do
For j:=(n*i)+1 to n*(i+1) do

7


 Sáng kiến kinh nghiệm
KQ:=KQ+S[a[j-(n*i)]+(n*i)];
End;
Begin
assign(g,'mhkhoa.out');
rewrite(g);
Doc_dl;
Xu_ly;
writeln(g,kq);
close(g)
End.

BT3: Nén xâu (mã hóa loạt dài)
(Đề thi chọn học sinh giỏi tỉnh lớp 12 – Năm học 2010-2011)
Một xâu kí tự có thể được nén theo cách sau: một xâu con gồm n kí tự giống
nhau (n>1), chẳng hạn gồm n kí tự “a” sẽ được ghi thành na.
Yêu cầu:
a) Với một xâu kí tự cho trước không có các chữ số, hãy nén xâu đó theo cách
đã nêu
b) Hãy giải nén một xâu kí tự sau khi đã được nén theo cách đã nêu.
Dữ liệu vào: tệp XAU. INP có cấu trúc
-

Dòng đầu tiên chứa xâu S không quá 254 kí tự và không có các chữ số


-

Dòng thứ hai chứa xâu X không quá 254 kí tự là xâu nén của một xâu nào
đó

Dữ liệu ra: tệp XAU.OUT có cấu trúc
-

Dòng đầu tiên chứa xâu nén của xâu S

-

Dòng thứ hai chứa xâu đã giải nén của xâu X

Ví dụ:
XAU.INP

XAU.OUT

Aaaabbcd

4a2bcd

3a4b2c

aaabbbbcc

Ý tưởng:
- Nén: Xác định đoạn liên tiếp có số các kí tự giống nhau là t. Nếu t >1 thì thông

báo t và kí tự đó, còn không thì chỉ thông báo kí tự đó.

8


 Sáng kiến kinh nghiệm

- Giải nén: Nếu X[i] là kí tự số thì chuyển X[i] sang số (so), thông báo kí tự
X[i+1] so lần; còn không thì thông báo X[i+1] 1 lần
Chương trình:
var f:text;
S,X:string;
procedure doc_dl;
var f:text;
begin
assign(f,'xau.inp');
reset (f);
readln(f,S);
readln(f,X);
close (f);
end;
procedure nen;
var i,j,t:integer;
k:char;
begin
i:=1;
while i<=length(s) do
begin
k:=s[i];
j:=i;

while k=s[i] do inc(i);
t:=i-j;
if t>1 then write(f,t,k)
else write(f,k);
end;
writeln(f);
end;
procedure giainen;
var i,j,so,code:integer;
begin
i:=1;
while i<=length(X) do
begin
if X[i] in ['0'..'9'] then
begin
val(X[i],so,code);
inc(i);
for j:=1 to so do write(f,X[i]);
end
else write(f,X[i]);
inc(i);
end;
end;
begin
assign(f,'xau.out');
rewrite(f);
doc_dl;
nen;
giainen;
close(f);

end.

BT4: Mã hóa xâu nhị phân

9


 Sáng kiến kinh nghiệm

(Đề thi chọn học sinh giỏi tỉnh lớp 11 – Năm học 2009-2010)
Xâu nhị phân là xâu chỉ chứa các kí tự 0 và 1. Để đảm bảo bí mật và tiết
kiệm dung lượng nhớ khi trao đổi thông tin với nhau, người ta có một cách để mã
hóa xâu nhị phân như sau: với một xâu nhị phân S, mã hóa nó thành một dãy số
nguyên T (T1,T2,…,TM) được tạo ra theo nguyên tắc sau:
-

Nếu kí tự đầu tiên của S là 0 thì T1 = 0, nếu là 1 thì T1=1

-

Nếu T1 = 0 thì tính từ trái sang phải của xâu S, T2 bằng số kí tự 0 liên tiếp,
T3 bằng số kí tự 1 liên tiếp sau đó, T4 bằng số kí tự 0 liên tiếp sau đó,…
cho đến hết xâu S

-

Nếu T1=1 thì tính từ trái sang phải của xâu S, T2 bằng số kí tự 1 liên tiếp,
T3 bằng số kí tự 0 liên tiếp sau đó, T4 bằng kí tự 1 liên tiếp sau đó,… cho
đến hết xâu S.


Ví dụ:
S= 0000110100111  T=(0,4,2,1,1,2,3)
S=11110011001  T=(1,4,2,2,2,1)
Yêu cầu: với mỗi dãy số mã hóa T cho trước nào đó, hãy đưa ra xâu S là xâu nhị
phân được mã hóa bởi dãy số T
Dữ liệu vào: Tệp văn bản MAHOA.INP có cấu trúc
-

Dòng đầu tiên ghi số M (M<50) là số lượng các số trong dãy số mã hóa T

-

Dòng tiếp theo ghi M số trong dãy số mã hóa T, các số ghi cách nhau ít nhất
một kí tự trống

Dữ liệu ra: Tệp văn bản MAHOA.OUT ghi xâu nhị phân S được mã hóa bởi dãy
số T
Ví dụ:
MAHOA.INP

MAHOA.OUT

7

0000110100111

0421123
5

1110111100


13142

10


 Sáng kiến kinh nghiệm

Chương trình:
const nmax=50;
var f1,f2:text;
m,i,j:integer;
a:array[1..nmax] of integer;
begin
assign(f1,'mahoa.inp');reset(f1);
assign(f2,'mahoa.out');rewrite(f2);
readln(f1,m);
for i:=1 to m do read(f1,a[i]);
if a[1]=0 then
begin
i:=2;
while i<=m do
begin
for j:=1 to a[i] do write(f2,0);
i:=i+1;
for j:=1 to a[i] do write(f2,1);
i:=i+1;
end;
end;
if a[1]=1 then

begin
for i:=2 to m do
if (i mod 2)=0 then
for j:=1 to a[i] do write(f2,1)
else for j:=1 to a[i] do write(f2,0);
end;
writeln(f2);
close(f1);close(f2);
end.

Dạng 2: Xâu đối xứng
Bài 1. Cho tệp văn bản XAU.INP chứa 1 xâu kí tự S. Lập trình đọc xâu S và đếm
xem trong xâu S có bao nhiêu từ là đối xứng (Từ là một dãy các kí tự, cách nhau
bởi dấu cách), kết quả ghi vào tệp XAU.OUT
Ví dụ
XAU.INP

XAU.OUT

abc aacdcaa bb ash radar

3

Chương trình:
VAR s : string;
dem : integer;
Procedure doc_dl;
var f:text;
begin
assign(f,'XAU.INP');

reset(f);
readln(f,s);
close(f);

11


 Sáng kiến kinh nghiệm
end;
function doixung(x : string) : boolean;
var y : string;
i : integer;
begin
y := '';
for i := length(x) downto 1 do y := y + x[i];
if x=y then doixung := true
else doixung := false;
end;
procedure xu_ly;
var i, len : integer;
t : string;
begin
i := 1; len := length(s);
repeat
while (s[i]=' ') and (i<=len) do inc(i);
if i>=len then break;
t := '';
while (s[i]<>' ') and (i<=len) do
begin
t := t + s[i];

inc(i);
end;
if doixung(t) then inc(dem);
until i >= len;
end;
Procedure ghi_kq;
var f:text;
begin
assign(f,'XAU.OUT');
rewrite(f);
writeln(f,dem);
close(f);
end;
BEGIN
Doc_dl;
Xu_ly;
Ghi_kq;
END.

Bài 2: chuỗi hạt
Người ta xâu N viên đá quý kích thước giống nhau thành một vòng đeo cổ, mỗi
viên có một màu trong số các màu được đánh số từ 1 đến 9. Để tăng tính độc đáo
và thẩm mỹ của vòng đá quý này, người ta lắp khóa tháo lắp vòng vào vị trí sao
cho khi mở khóa ta được một dây đá quý có tính chất: không phụ thuộc vào việc
cầm đầu dây nào bên tay phải và đầu dây kia bên tay trái, ta đều được một chuỗi
hạt hoàn toàn giống nhau, nghĩa là viên đá thứ i tính từ trái sang luôn có màu j
không phụ thuộc vào cách cầm.
Yêu cầu: Xác định số cách khác nhau có thể lắp khóa tháo lắp vòng
Input: Tệp HAT.INP có dạng:


12


 Sáng kiến kinh nghiệm

-

Dòng 1 ghi các số nguyên từ 1 đến
9, số thứ i chỉ thị màu viên đá thứ i,
các số ghi liên tiếp nhau

HAT.INP
22343

HAT.OUT
1
2

Output: ghi ra tệp HAT.OUT

– Dòng 1 ghi Số cách khác nhau có thể lắp khóa, nếu không ghi số 0
– Dòng 2: ghi Vị trí lắp khóa
Ý tưởng:
• Nhân đôi xâu ban đầu
• Viết chương trình con kiểm tra 1 xâu có độ dài N có phải là đối xứng hay
không.
• Kiểm tra từng xâu con độ dài N bắt đầu từ vị trí i (i= 1,...,N), nếu nó là xâu
đối xừng thì đặt khóa tại vị trí i.
Chương trình:
const nmax=255;

var S:string;
kq:array[1..nmax] of byte;
dem:byte;
procedure doc_dl;
var f:text;
begin
assign(f,'hat.inp');
reset(f);
read(f,S);
close(f);
end;
Function doi_xung(S:string):boolean;
var i,j:byte;
kt:boolean;
begin
kt:=false;
i:=1; j:=length(S);
while (ibegin
inc(i);
dec(j);
end;
if i>=j then kt:=true;
doi_xung:=kt;
end;
procedure Xu_ly;
var i,n:byte;
S1,S2:string;
begin
n:=length(S);

S1:=S+S;
dem:=0;
for i:=1 to n do

13


 Sáng kiến kinh nghiệm
begin
S2:=copy(S1,i,n);
if doi_xung(S2) then
begin
dem:=dem+1;
kq[dem]:=i;
end;
end;
end;
procedure ghi_kq;
var f:text;
i:byte;
begin
assign(f,'hat.out');
rewrite(f);
writeln(f,dem);
for i:=1 to dem do write(f,kq[i],' ');
close(f);
end;
begin
doc_dl;
Xu_ly;

ghi_kq;
end.

BT2: Robot công nghiệp
(Đề thi chọn học sinh giỏi tỉnh lớp 11 – Năm học 2010-2011)
Trong một nhà máy có trang bị loại Robot công nghiệp để thực hiện việc tự
động hóa gia công các sản phẩm. Việc gia công các sản phẩm của Robot được thực
hiện đồng thời trên hai sản phẩm cùng một lúc theo tiến trình: với mỗi loại thao tác
gia công được Robot thực hiện trên sản phẩm thứ nhất xong rồi chuyển sang thực
hiện trên sản phẩm thứ hai. Để hoàn thành một sản phẩm, Robot có thể thực hiện
tới N loại thao tác gia công (N<=24) và mỗi loại thao tác gia công được thực hiện
trên một sản phẩm nào đó rồi thì không thực hiện lại trên sản phẩm đó nữa. Robot
thực hiện bằng lệnh là một dãy kí tự in hoa, mỗi kí tự là lệnh thực hiện cho một
loại thao tác gia công. Lệnh thực hiện các loại thao tác gia công khác nhau là các
kí tự khác nhau. Việc đọc dòng lệnh và thực hiện lệnh của Robot được tiến hành
theo các chu trình như sau:
-

Chu trình thứ nhất: Đọc kí tự thứ nhất, thực hiện lệnh tương ứng trên sản
phẩm thứ nhất. Tiếp theo đọc kí tự thứ N, thực hiện lệnh tương ứng trên sản
phẩm thứ hai.

-

Chu trình thứ hai: Đọc kí tự thứ hai, thực hiện lệnh tương ứng trên sản phẩm
thứ nhất. Tiếp theo đọc kí tự thứ N-1, thực hiện lệnh tương ứng trên sản
phẩm thứ hai.

14



 Sáng kiến kinh nghiệm

-

Chu trình thứ ba: Đọc kí tự thứ ba, thực hiện lệnh tương ứng trên sản phẩm
thứ nhất. Tiếp theo đọc kí tự thứ N-2, thực hiện lệnh tương ứng trên sản
phẩm thứ hai.

-

...

Tương tự với các chu trình còn lại để đọc hết dòng lệnh
Với một xâu S các kí tự in hoa có số lượng các kí tự là chẵn và không quá Nx2,
hãy xác định xem nó có phải là một dòng lệnh của Robot đã nói ở trên hay không?
Dữ liệu vào: Tệp văn bản ROBOT.INP có cấu trúc:
-

Dòng đầu tiên ghi một số là độ dài xâu S

-

Dòng thứ hai ghi xâu S.

Dữ liệu ra: Tệp văn bản ROBOT.OUT ghi thông báo ‘CO’ nếu xâu S là dòng lệnh
của Robot, ngược lại ghi thông báo ‘KHONG’
Ví dụTệp
ROBOT.INP


Tệp ROBOT.OUT

6

CO

CBAABC
Tệp ROBOT.INP

Tệp ROBOT.OUT

6

KHONG

ACBDCA
Ý tưởng:
Thực chất của bài toán là kiểm tra xem với 1 xâu S cho trước gồm N (N
chẵn và N<=24) các kí tự in hoa có phải là xâu đối xứng và có khác nhau theo từng
cặp đối xứng hay không
• Kiểm tra nửa đầu xâu S xem các kí tự có khác nhau không? Nếu nửa đầu xâu
mà các kí tự không khác nhua từng đôi một thì đưa ra kết luận xâu S không
phải là lệnh của Robot và dừng thuật toán
• Nếu nửa đầu xâu S có các kí tự khác nhau từng đôi một thì kiểm tra tính đối
xứng của xấu S
Chương trình:

15



 Sáng kiến kinh nghiệm
Var S: string;
n,i,j,dem:integer;
f:text;
Procedure Doc_dl;
begin
assign(f,'robot.inp');
reset(f);
readln(f,n);
readln(f,s);
close(f);
end;
BEGIN
Doc_dl;
assign(f,'robot.out');
rewrite(f);
For i := 1 to (N div 2) - 1 do
Begin
Dem:=0;
For j := i+1 to N div 2 do
If S[i]=S[j] then
Begin
Inc(dem);
If dem <> 0 then
Begin write(f,'KHONG'); close(f); halt; end;
End;
End;
i:=1; j:=N;
while (ibegin

inc(i);
dec(j);
end;
If i>j then writeln(f,'CO')
Else write(f,'KHONG');
close(f);
END.

Bài tập đề nghị
Cho một xâu S gồm không quá 200 kí tự. Cho biết S có phải là xâu đối
xứng hay không? Nếu không, cho biết số kí tự ít nhất cần thêm vào S để S trở thành
xâu đối xứng.
Dữ liệu: Vào từ file văn bản XAU.INP, gồm duy nhất 1 dòng ghi xâu S.
Kết quả: Ghi ra file văn bản XAU.OUT, duy nhất số k là số kí tự ít nhất cần thêm
vào S để S trở thành xâu đối xứng. Nếu xâu S đã cho là đối xứng thì ghi k = 0.
Ví dụ:
XAU.INP

XAU.OUT

XAU.INP

XAU.OUT

RADAR

0

TOMATO


3

Dạng 3: Biến đổi xâu
BT1: Hãy lập trình:
16


 Sáng kiến kinh nghiệm

-

Nhập xâu bất kì từ bàn phím

-

Chuẩn hóa xâu theo các quy tắc sau:
+ Xóa các dấu cách ở đầu xâu nếu có
+ Xóa các dấu cách ở cuối xâu nếu có
+ Thay dãy nhiều dấu cách liên tiếp bằng một dấu cách

-

Đưa kết quả đã chuẩn hóa ra màn hình

Ý tưởng:
• Thực hiện tìm từ đầu xâu đến cuối xâu, nếu có 2 dấu cách liên tiếp thì thực
hiện xóa đi 1 dấu cách.
• Nếu kí tự đầu tiên là dấu cách thì thực hiện xóa nó đi
• Nếu kí tự cuối cùng là dấu cách thì thực hiện xóa nó đi
Chương trình:

Var S:string;
begin
write('Nhap vao mot xau S bat ky: ');
readln(S);
While pos(' ',S) <>0 do delete(S,pos(' ',S),1);
if S[1]=' ' then delete(S,1,1);
if S[length(S)]=' ' then delete(S,length(s),1);
write('xau S sau khi chuan hoa la: ',S);
readln;
end.

Bài 2. Thay thế từ
Hai file INPUT1.TXT và INPUT2.TXT được cho như sau: File
INPUT1.TXT chứa một đoạn văn bản bất kì. File INPUT2.TXT chứa không quá
50 dòng, mỗi dòng gồm hai từ: từ đầu là từ đích và từ sau là từ nguồn. Hãy tìm
trong file INPUT1.TXT tất cả các từ là từ đích và thay thế chúng bằng các từ
nguồn tương ứng. Kết quả ghi vào file KQ.OUT (sẽ là một đoạn văn bản tương tự
như trong file INPUT1.TXT nhưng đã được thay thế từ đích bởi từ nguồn).
Dữ liệu vào
- File INPUT1.TXT chứa đoạn văn bản sau:
Nam moi sap den roi, ban co zui khong?
Chuc cac ban don mot cai Tet that vui ve va hanh phuc.
Chuc ban luon hoc gioi!
- File INPUT2.TXT chứa các dòng sau:

17


 Sáng kiến kinh nghiệm


ban em
zui vui
Dữ liệu ra
File KQ.OUT sẽ chứa đoạn văn bản sau:
Nam moi sap den roi, em co vui khong?
Chuc cac em don mot cai Tet that vui ve va hanh phuc.
Chuc em luon hoc gioi!
Chương trình:
program thaythetu;
var
source,des:array[1..50]of string;
n:byte;
procedure Doc_dl;
var
i:byte;
s:string;
f:text;
begin
assign(f,'input2.txt');
reset(f);
n:=0;
while not eof(f) do
begin
readln(f,s);
inc(n);
while (s<>'')and(s[1]=' ') do
delete(s,1,1);
if i>0 then
begin
i:=pos(' ',s);

des[n]:=copy(s,1,i-1);
while (i<=length(s))and(s[i]=' ') do
i:=i+1;
source[n]:=copy(s,i,length(s)-i+1);
end;
end;
end;
procedure thay_the;
var
f,g:text;
s:string;
i,k:byte;
begin
assign(f,'input1.txt');
reset(f);
assign(g,'kq.out');
rewrite(g);
while not eof(f) do
begin
readln(f,s);
for k:=1 to n do
for i:=1 to length(s)-length(des[k])+1 do
if des[k]=copy(s,i,length(des[k])) then

18


 Sáng kiến kinh nghiệm
begin


delete(s,i,length(des[k]));
insert(source[k],s,i);
i:=i+length(source[k]);

end;
writeln(g,s);
end;
close(f);
close(g);

end;
Begin
init;
replace;
End.

Bài 3. Chèn Xâu
Cho một xâu S = ’123456789’ hãy tìm cách chèn vào S các dấu '+' hoặc '-'
để thu được số M cho trước (nếu có thể). Số M nguyên được nhập từ bàn phím.
Trong file Output Chenxau.Out ghi tất cả các phương án chèn (nếu có) và ghi
"Khong co" nếu như không thể thu được M từ cách làm trên.
Ví dụ: Nhập M = 5, một trong các phương án đó là: '12-34+5-67+89';
M = 8, một trong các phương án đó là: '-1-2-34-5+67-8-9';
Ý tưởng:
Ta sử dụng phương pháp đệ quy quay lui tìm tất cả các nghiệm để giải bài
toán này
Chương trình:
Uses crt;
Const dau: array[1..3] of String[1]= ('', '-', '+');
s:array[1..9] of char=('1','2','3','4','5','6','7','8','9');

Var d:array[1..9] of String[1];
m:longInt;
f:text;
k:integer;
found:boolean;
Procedure Nhap_dl;
Begin
Write('Cho M=');
Readln(m);
found:=false;
end;
Function tinh(s:string):longint;
Var i,t:longint;
code:integer;
Begin
i:=length(s);
While not(s[i] in ['-','+']) and (i>0) do dec(i);
val(copy(s,i+1,length(s)-i),t,code);
If i=0 then begin tinh:=t; exit; end
else
begin

19


 Sáng kiến kinh nghiệm
delete(s,i,length(s)-i+1);
If s[i]='+' then tinh:=t+tinh(s);
If s[i]='-' then tinh:=tinh(s)-t;


end;
End;
Procedure Kiem_tra(i:integer);
Var st:string; j:integer;
Begin
st:='';
For j:=1 to i do st:=st+d[j]+s[j];
If Tinh(st) = m then begin writeln(f,st); found:=true; end;
End;
Procedure Try(i:integer);
Var j:integer;
Begin
for j:=1 to 3 do
begin
d[i]:=dau[j];
If i<9 then try(i+1);
if i=9 then Kiem_tra(i);
end;
End;
BEGIN
Clrscr;
Nhap_dl;
Assign(f,'chenxau.out');Rewrite(f);
for k:=1 to 2 do
begin
d[1]:=dau[k];
Try(2);
end;
If not found then write(f,'khong co ngiem');
Close(f);

END.

Bài tập đề nghị
Bài 2 Biến đổi xâu
Cho trước một xâu nhị phân có độ dài bất kỳ. Cần biến đổi xâu nhị phân này về
dạng toàn số 0. Các phép biến đổi chỉ có thể là một trong các loại sau:
- Biến đổi xâu con 11 thành 00.
- Biến đổi xâu con 010 thành 000.
Hãy chỉ ra một cách biến đổi xâu đã cho thành xâu có toàn 0.
Dữ liệu vào: từ file XAUNP.INP xâu nhị phân độ dài bất kỳ.
Kết quả: ghi ra file XAUNP.OUT như sau:
- Dòng đầu tiên chứa xâu ban đầu.
- Sau đó mỗi dòng là một xâu tiếp theo sau một phép biến đổi. Xâu cuối cùng là
xâu toàn 0.
- Nếu không biến đổi được thì ghi "Khong the bien doi duoc".
Ví dụ:
XAUNP.INP

XAUNP.OUT

XAUNP.INP

20

XAUNP.OUT


 Sáng kiến kinh nghiệm

11010011


11010011
11010000
00010000
00000000

10101101

Khong the bien doi duoc

Bài 3 Chuẩn hoá 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 để kiểm tra và đưa một đoạn văn bản về dạng văn bản chuẩn.
Dữ liệu vào: từ file BAI3.INP
Kết quả: ghi ra file BAI3.OUT văn bản đã được chuẩn hoá.
Ví dụ
XAU.INP
XAU.OUT
HOANG SA LA CUA VIET NAM . HOANG SA LA CUA VIET NAM
Dạng 4: Sự xuất hiện các kí tự
BT1: Hãy lập trình
-

Nhập xâu S chỉ chứa các kí tự La tinh in thường và các kí tự số từ 0 đến 9


-

Đếm và đư ra màn hình số lượng kí tự khác nhau trong xâu S.

Ý tưởng:
Với mỗi i (i=1,…,length(S)-1), ta thực hiện xóa tất cả kí tự giống S[i] trong
xâu S kể từ vị trí i+1. Số kí tự khác nhau trong xâu S chính là độ dài xâu S còn lại.
Chương trình:
uses crt;
Var s,s1:string;
i:integer;
begin
clrscr;
writeln('nhap vao xau ki tu s: ');
readln(s);
for i:=1 to length(s)-1 do
begin
S1:=copy(s,i+1,length(s)-i);
while pos(s[i],s1) <>0 do delete(s1,pos(s[i],s1),1);

21


 Sáng kiến kinh nghiệm
S:=copy(s,1,i)+s1;
end;
writeln('so luong ki tu khac nhau la:',length(s));
readln;
end.


BT2: Xâu kí tự
Có không quá 100 chiến sĩ công an tham gia trong một chiến dịch truy quét
tội phạm ở tỉnh X. Các chiến sĩ công an được chia thành không quá 26 đội. Để dễ
điều hành, bộ chỉ huy chiến dịch quy định kí hiệu cho mỗi đội là một chữ cái in
thường nằm trong khoảng từ “a” đến “z”. Hai đội khác nhau thì kí hiệu khác nhau.
Các chiến sĩ công an thuộc đội nào thì được gắn 1 kí hiệu của đội đó. Nếu lấy kí
hiệu đã gắn cho tất cả chiến sĩ công an đã tham gia chiến dịch ghép lại thì được
một xâu kí tự
Hãy xác định số lượng các chiến sĩ công an trong mỗi đội
Dữ liệu vào: tệp XAU.INP chứa một xâu kí tự là kết quả của việc ghép kí hiệu đã
gắn cho tất cả chiến sĩ công an tham gia.
Dữ liệu ra: tệp XAU.OUT có không quá 26 dòng, mỗi dòng ghi kí hiệu của mỗi
đội và số lượng thành viên trong đội
Ví dụ:
XAU.INP

XAU.OUT

abcad

a2
b1
c1
d1

Ý tưởng:
• Khai báo mảng gồm 26 kí tự dùng để đếm số lần xuất hiện mỗi kí tự
Dem: array[‘a’..’z’] of byte;
• Việc đếm sẽ được thực hiện bằng câu lênh:
For i:= 1 to length(S) do inc (dem[S[i]]);

Chương trình:

22


 Sáng kiến kinh nghiệm
VAR S:string;
dem:array['a'..'z'] of byte;
Procedure Doc_dl;
var f:text;
begin
assign(f,'xau.inp');
reset(f);
readln(f,s);
close(f);
end;
Procedure Xu_ly;
var f:text;
i:byte;
ch:char;
begin
assign(f,'xau.out');
rewrite(f);
for i:=1 to length(s) do inc(dem[s[i]]);
for ch:='a' to 'z' do
if dem[ch] <>0 then writeln(f,ch,dem[ch]);
close(f);
end;
BEGIN
fillchar(dem,sizeof(dem),0);

doc_dl;
Xu_ly;
END.

Bài tập đề nghị
Bài 1: Liệt kê chữ cái
Cho một văn bản chứa trong một text file. Bạn hãy viết chương trình liệt kê
các chữ cái chỉ có mặt trong văn bản đúng một lần theo thứ tự của bảng chữ cái
(không phân biệt chữ hoa và chữ thường).
- Dữ liệu vào: file DEM_CHU.INP gồm nhiều dòng chứa các ký tự trong file.
- Dữ liệu ra: file DEM_CHU.OUT
Mỗi dòng ghi các ký tự chỉ xuất hiện đúng một lần trong file theo yêu cầu đề ra.
Ví dụ:
DEM_CHU.INP
DEM_CHU.OUT
C
NAM MOI HANH PHUC
I
O
P
U
Dạng 5: Xâu con
Câu 1: Sắp xếp xâu.

23


 Sáng kiến kinh nghiệm

Người ta định nghĩa: Từ là một nhóm ký tự đứng liền nhau.

Cho một xâu S 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 abcd abc
acb abc abcd abcde
Ý tưởng:
- Thực hiện chuẩn hóa xâu S
- Dùng 1 mảng không quá 20 phần tử, mỗi phần tử là một xâu kí tự để chứa các từ
trong xâu.
- Sắp xếp các phần tử mảng theo độ dài của các phần tử
Chương trình:
Program sap_xau;
const f1='sapxau.inp';
f2='sapxau.out';
type mm=array[1..20] of string;
var a:mm;
s:string;
d:byte;
procedure doc_dl;
var f:text;
begin

assign(f,f1);
reset(f);
readln(f,s);
close(f);
end;
procedure chuan_hoa(var St:string);
begin
while pos(' ',St)<>0 do delete(St,pos(' ',St),1);
if St[1]=' ' then delete(St,1,1);
if St[length(St)]=' ' then delete(St,length(St),1);
end;
procedure xu_ly;
var j,i:byte;
tg:string;
begin
chuan_hoa(S);
s:=s+' ';
for i:=1 to 20 do a[i]:='';
i:=0;
while s<>'' do

24


 Sáng kiến kinh nghiệm
begin
i:=i+1;
a[i]:=copy(s,1,pos(' ',s)-1);
delete(s,1,pos(' ',s));
end;

d:=i;
for j:=d downto 2 do
for i:=1 to j-1 do
if length(a[i])>length(a[i+1]) then
begin
tg:=a[i];
a[i]:=a[i+1];
a[i+1]:=tg;
end;
end;
procedure ghi_kq;
var i:integer;
f:text;
begin
assign(f,f2);
rewrite(f);
for i:=1 to d do write(f,a[i],' ');
close(f);
end;
begin
doc_dl;
xu_ly;
ghi_kq;
end.

BT2: Dãy ngoặc đúng
(Đề thi chọn học sinh giỏi tỉnh lớp 11 – Năm học 2011-2012)
Xâu S chỉ bao gồm các kí tự ngoặc mở “(“ và ngoặc đóng “)”. Xâu S xác
định một cách đặt ngoặc đúng nếu thỏa mãn các điều kiện sau:
-


Số ngoặc mở bằng số ngoặc đóng

-

Nếu duyệt từ trái qua phải, số lượng ngoặc mở luôn lớn hơn hoặc bằng số
lượng ngoặc đóng

Ví dụ, xâu “(( )(( )))” xác định một cách đặt ngoặc đúng, còn xâu “( ))( ))” là một
cách đặt ngoặc sai.
Yêu cầu: Hãy xác định đoạn ngoặc đúng dài nhất
Dữ liệu vào là tệp văn bản NGOAC.INP chứa một dòng không quá 255 dấu ngoặc
Dữ liệu ra là tệp văn bản NGOAC.OUT:
-

Dòng đầu tiên ghi độ dài của dãy ngoặc đúng dài nhất

-

Dòng thứ hai ghi chỉ số đầu và chỉ số cuối của đoạn ngoặc đúng đó

-

Nếu không có đoạn ngoặc đúng nào thì ghi vào tệp thông báo “Khong co”

25


×