PHÇN A. §ÆT VÊN §Ò
I.
C¬ së khoa häc vµ thùc tiÔn trong viÖc lùa chän ®Ò tµi
Trong
thùc tiÔn d÷ liÖu vµo cña c¸c bµi to¸n ®Òu liªn quan ®Õn c¸c kiÓu d÷ liÖu kh¸c
nhau, ®Ó tiÖn cho viÖc lËp tr×nh vµ xö lý d÷ liÖu chóng ta thêng ®a d÷ liÖu
®ã vÒ c¸c d¹ng kiÓu d÷ liÖu chuÈn hoÆc kiÓu d÷ liÖu
cã cÊu tróc, mét trong nh÷ng kiÓu d÷ liÖu chuÈn ®ã lµ kiÓu x©u.
Qua
qu¸ tr×nh tham gia gi¶ng d¹y vµ båi dìng häc sinh giái chóng t«i nhËn thÊy d÷
liÖu kiÓu x©u thêng gÆp rÊt nhiÒu trong c¸c bµi to¸n vµ vËn dông linh ho¹t c¸c
thao t¸c xö lý trªn kiÓu d÷ liÖu nµy vµo bµi to¸n kh«ng ph¶i lµ dÔ. Víi mong
muèn phÇn nµo gióp häc sinh còng nh gi¸o viªn trong viÖc t×m ra lêi gi¶i cho
mét sè bµi to¸n liªn quan tíi kiÓu d÷ liÖu x©u dÔ dµng h¬n, chóng t«i xin giíi Chuyªn
®Ò båi dìng kiÓu d÷ liÖu x©u mµ chóng t«i ®· ¸p dông cã hiÖu qu¶ trong qu¸
tr×nh gi¶ng d¹y.
II.
Môc ®Ých, nhiÖm vô cña viÖc thùc hiÖn ®Ò tµi nghiªn cøu
NhËn
thÊy viÖc ®a ra c¸c bµi to¸n trªn kiÓu d÷ liÖu x©u cïng ph¬ng ph¸p gi¶i chóng
b»ng ng«n ng÷ lËp tr×nh nµo ®ã (hiÖn nay häc sinh phæ th«ng ®ang sö dông
ng«n ng÷ lËp tr×nh Pascal nªn c¸c vÝ dô vµ bµi tËp chóng t«i giíi thiÖu sö dông
ng«n ng÷ Free Pascal ®Ó minh häa) lµ rÊt cÇn thiÕt nh»m gióp cho gi¸o viªn,
còng nh häc sinh hÖ thèng l¹i c¸c kiÕn thøc vÒ c¸c thao t¸c trªn kiÓu d÷ liÖu
x©u vµ ph©n d¹ng bµi tËp, tõ ®ã ¸p dông cho c¸c bµi to¸n cô thÓ. Chóng t«i ®Ò
ra môc ®Ých, nhiÖm vô cô thÓ cña viÖc thùc hiÖn ®Ò tµi:
- Giíi thiÖu c¸ch khai b¸o vµ truy xuÊt ®Õn
kiÓu d÷ liÖu x©u, trong phÇn nµy ®Ò cËp ®Õn mét kiÓu d÷ liÖu x©u cã ®é dµi rÊt
lín phï hîp víi thùc tiÔn c¸c bµi to¸n mµ cha ®îc ®Ò cËp ®Õn trong s¸ch gi¸o
khoa lµ ansistring.
- Giíi thiÖu
mét sè phÐp to¸n trªn kiÓu d÷ liÖu x©u, ®Æc biÖt phÇn nµy cã cung cÊp thªm mét
sè hµm, thñ tôc cha ®îc giíi thiÖu trong bµi 12 s¸ch gi¸o khoa tin häc 11,
®ång thêi ®a ra mét sè vÝ dô t¬ng øng ®Ó häc sinh dÔ dµng sö dông.
- HÖ thèng c¸c
bµi to¸n díi d¹ng mét sè d¹ng bµi tËp thêng gÆp gióp cho gi¸o viªn vµ häc
sinh phÇn nµo nhËn d¹ng vµ gi¶i mét sè bµi tËp liªn quan.
- Giíi thiÖu
mét sè bµi tËp ¸p dông.
V× thÕ, cÊu tróc néi dung gåm:
Môc I. Khai b¸o vµ truy xuÊt ®Õn phÇn
tö kiÓu x©u.
Môc II. C¸c phÐp hµm vµ thñ
tôc chuÈn trªn x©u
Môc III. C¸c d¹ng to¸n thêng
gÆp.
Môc IV. Bµi tËp ¸p dông.
III. §èi tîng, thêi gian vµ ph¬ng ph¸p nghiªn
cøu
1. §èi tîng nghiªn cøu
Bµi viÕt
SKKN "Chuyªn ®Ò båi dìng kiÓu d÷ liÖu x©u" cã ®èi tîng nghiªn cøu lµ c¸c bµi to¸n trªn
d÷ liÖu kiÓu x©u.
2. Thêi gian nghiªn cøu
SKKN ®îc thùc hiÖn trong n¨m häc 2013-2014
3. Ph¬ng ph¸p nghiªn cøu
§Ó hoµn thµnh SKKN nµy chóng t«i sö dông phèi
kÕt hîp nhiÒu ph¬ng ph¸p, trong ®ã ph¬ng ph¸p chñ yÕu lµ nghiªn cøu tµi liÖu,
tham kh¶o ý kiÕn cña cÊp trªn vµ ®ång nghiÖp.
PhÇn B. néi dung
Để xử lý các chuỗi văn bản, Pascal đưa
ra một kiểu dữ liệu mới gọi là xâu ký tự và được định nghĩa bằng từ khóa
STRING. Xâu ký tự là dữ liệu bao gồm một dãy các ký tự trong bảng mã ASSCII.
Tuy nhiên độ dài của String tối đa chỉ 255 mà thực tế thì ta thường gặp xâu có
độ dài rất lớn cỡ hàng ngàn, vậy có cách nào để có thể khắc phục được điều đó,
chúng tôi xin trình bày một số nội dung mà chúng tôi đã tìm hiểu và vận dụng có
hiệu quả trong quá trình giảng dạy và bồi dưỡng đội tuyển.
1. Cách khai báo:
Var: STRING[độ dài của xâu];
- Xâu ký tự trong bộ nhớ nó chiếm số
byte bằng số ký tự cực đại được khai báo cộng với byte đầu tiên chứa số ký tự
hiện có của xâu. Độ dài tối đa của xâu ký tự là 255.
-
Ngoài ra có các kiểu khai báo khác của xâu như:
+
Shortstring: Chính là String.
+
longstring: là mảng ký tự có kiểu char. Thông thường kiểu char có kích thước 16
bit nên mảng có kích thước tối đa 16 bit = 65535 ký tự.
+
ansistring (chỉ có trong free pascal mà không có trong turbo pascal) có kích
thước gần 2GB = 230 B nên thường được xem là vô hạn.
2. Cách nhập/xuất:
Cách đọc hay viết kiểu STRING cũng
tương tự như các kiểu dữ liệu khác, ta sử dụng các thủ tục READ, hoặc WRITE.
Ví dụ: Readln(st); Writeln(st);
3. Truy cập từng phần
tử của xâu ký tự:
Việc truy
cập đến phần tử trong xâu tương tự mảng 1 chiều được thông qua tên
biến kiểu STRING và chỉ số của nó
Ví dụ: St
:= 'Le Thanh Lam'; write(st[4]);
-> Kết quả: cho ra
chữ T.
II. CÁC THAO TÁC TRÊN XÂU KÝ TỰ
1. Phép cộng xâu:
Ví dụ: st1:=’tin’; st2:=’ hoc’; St=st1 +
st2;
-> St = ‘tin hoc’
2. Phép so
sánh:
Hai xâu ký tự có thể so sánh với nhau
bằng các phép so sánh =, >, <…
Nguyên tắc so sánh thực hiện như sau, chúng sẽ đem từng ký tự tương ứng với nhau để so sánh, xâu nào có ký tự có số thứ tự trong bảng mã ASCII lớn hơn thì xâu đó lớn hơn.
Nguyên tắc so sánh thực hiện như sau, chúng sẽ đem từng ký tự tương ứng với nhau để so sánh, xâu nào có ký tự có số thứ tự trong bảng mã ASCII lớn hơn thì xâu đó lớn hơn.
Hai xâu ký tự được gọi là bằng nhau
khi chúng hoàn toàn giống nhau (có độ dài như nhau).
Ví dụ: st1:=’tin’; st2:=’ hoc’; khi đó
st1>st2
3. Các thủ tục và
hàm chuẩn xử lý xâu ký tự
a. Hàm
length(st): cho độ dài thực của xâu ký tự st
Ví dụ: st:=’tin hoc’ thì LENGTH(st)
cho bằng 7.
b. Hàm
upcase(ch): Cho ký tự hoa của ký tự ch
Ví dụ: ch:= 'a'; ch:= upcase(ch) ® ch = 'A'
Ví dụ: Viết đoạn chương trình nhập vào
một xâu ký tự. Đổi xâu đó sang chữ in hoa rồi in kết quả ra màn hình
var s,s1:string;
i:integer;
begin
write('nhap xau s:');
readln(s);
s1:='';
for i:=1 to length(s) do s1:=s1+
upcase(s[i]);
write(s1);
readln;
end.
c. Hàm
Ord(ch): Cho mã của ký tự ch trong bảng mã ASCII
Ví dụ: ch:='a'; n:= Ord(ch) ® n= 97
d. Hàm Chr(n): Cho ký tự có mã là n
Ví dụ: Viết đoạn chương
trình nhập vào một xâu ký tự. Đổi xâu đó sang chữ thường rồi in xâu đó ra màn
hình theo thứ tự ngược lại
* Ý tưởng: Để thực hiện
chuyển đổi ký tự ch ở dạng hoa sang dạng thường trước hết ta sử dụng hàm
ord(ch) để lấy mã ký tự đó, sau đó sử dụng hàm chr(ord(ch)+32) để được ký tự
thường của ký tự hoa ch (vì mã của ký tự hoa ch lệch mã ký tự thường tương ứng
là 32 như: ord('A')=65, ord('a')=97)
var s,s1:string;
i:integer;
begin
write('nhap xau s:');
readln(s);
s1:='';
for i:=1 to length(s) do
if s[i] in ['A'..'Z'] then s1:=s1+
chr(ord(s[i])+32)
else s1:=s1+s[i];
for i:=length(s1) downto 1 do write(s1[i]);
readln;
end.
e. Thủ
tục DELETE(st, pos, num): xóa num ký tự trong xâu st kể từ vị trí pos
Ví dụ: st= ‘tin hoc’; Delete(st,4,4);
lúc đó st cho ra là ‘tin’
f. Hàm
POS(st1,st2): hàm cho vị trí tìm thấy đầu tiên của xâu s1 trong xâu s2.
Ví dụ: POS(‘tin’,‘tin hoc’) = 1
Ví dụ: POS(‘tin’,‘tin hoc’) = 1
Ví dụ: Viết đoạn chương trình nhập vào
một xâu ký tự. In ra xâu đó sau khi đã xóa hết ký tự trắng thừa trong xâu (Ký
tự trắng thừa là các ký tự đầu xâu, cuối xâu và nếu giữa xâu có 2 ký tự trắng
liên tiếp nhau thì có một ký tự trắng thừa)
* Ý tưởng:
- Sử dụng hàm Pos(' ',s) để biết được
vị trí i nào đó xuất hiện ký tự trắng và sử dụng thủ tục Delete(s,i,1) để xóa
ký tự thứ i trong xâu s
- Để xóa ký tự trắng đầu xâu ta thực
hiện lệnh:
while s[1]=' ' do delete(s,1,1);
- Để xóa ký tự trắng cuối
xâu ta thực hiện lệnh:
while s[length(s)]
= ' ' do delete(s,length(s),1);
- Để xóa ký tự trắng giữa xâu ta thực
hiện lệnh:
while pos(' ',s)<>0 do
delete(s, pos(' ',s),1);
var s:string;
begin
write('nhap xau s:');
readln(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);
write(s);
readln;
end.
g. Thủ tục INSERT(st1, st2, pos): Thủ tục cho kết quả bằng cách
chèn xâu ký tự có tên là st1 vào xâu st2 tại vị trí pos, những ký tự đứng sau
pos sẽ được dời về phía sau của xâu ký tự st2.
Ví dụ: st1:= ‘tin ‘;
st2:=’hoc kho’; INSERT(st1,st2,5) ® st2=’hoc tin kho’;
Ví dụ: Viết đoạn chương trình nhập vào
3 xâu s1, s2, s (với xâu s1 xuất hiện một và chỉ đúng 1 lần trong xâu s). Tìm
và thay thế xâu s1 thành xâu s2 trong xâu s.
Chẳng hạn: s1 := 'hoc'; s2:= 'bai
tap'; s :='hoc tin hoc'; kết quả sau khi thay thế s1 thành s2 là s = 'bai tap
tin hoc'
var s1,s2,s: string;
i:byte;
begin
write('nhap s1:');
readln(s1);
write('nhap s2:');
readln(s2);
write('nhap xau s:');
readln(s);
i:= pos(s1,s);
delete(s,i,length(s1));
insert(s2,s,i);
write(s);
readln;
end.
h. Thủ
tục STR(value, st): Thủ tục này thực hiện việc chuyển đối giá trị kiểu
số(value) sang dạng xâu ký tự và gán cho biến st.
Ví dụ: n:=2014; STR(n,st) sẽ cho kết
quả xâu st là: st=’2014’;
i. Thủ
tục VAL(st, value,code) đổi một xâu ký tự st sang dạng số và gán cho
biến value, nếu biến đối thành công thì code sẽ nhận giá trị bằng 0. ngược lại
thì cho giá trị khác không
Ví dụ: VAL(‘2014’,value,code) lúc này
code sẽ nhận giá trị bằng 0 và value=2014
Ví dụ: Viết đoạn chương trình nhập vào
số tự nhiên a có n con số. Hãy tạo ra số mới b từ số a bằng cách in ngược có số
xuất hiện trong a. Chẳng hạn số a = 123 thì b=321
var a,b:Qword;
s,s1:string; i,code:longint;
begin
write('nhap a:');
readln(a);
str(a,s);
s1:='';
for i:=length(s) downto 1 do s1:=s1+s[i];
val(s1,b,code);
write(b);
readln;
end.
j. Hàm
CONCAT(s1,s2,…,sn): hàm cho ra 1 xâu mới bằng cách nối đuôi các xâu
s1,s2,…,sn lại với nhau.
Ví dụ: CONCAT(‘hoc ’, ‘tin ’) = ‘hoc
tin’;
k. Hàm
COPY(st, pos, num): sao chép trong xâu st, num ký tự tại vị trí pos,
Ví dụ: st=’tin hoc’; COPY(st,5,3) =
‘hoc’;
Ví dụ: Viết đoạn chương trình nhập vào
một xâu S (không có dấu cách vô nghĩa). Đưa ra từ dài nhất xuất hiện trong xâu S. Chẳng hạn: s = 'xin chao ban' ®kết quả tìm được là
từ 'chao'
* Ý tưởng: Dùng hàm pos để xác định ví
trí ký tự trống xuất hiện đầu tiên trong xâu s. Từ đó xác định độ dài của từ
đầu tiên trong s. Nếu ta thực hiện xóa đi từ đầu tiên trong xâu s và lặp lại
thao tác trên ta sẽ tìm được từ tiếp theo, đồng thời ta sẽ tìm được từ có độ
dài lớn nhất.
* Chương trình:
var s,tumax:string;
begin
write('nhap xau s:');
readln(s);
while pos(#32,s)<>0 do
begin
if pos(#32,s)>length(tumax) then
tumax:=copy(s,1,pos(#32,s));
delete(s,1,pos(#32,s));
end;
writeln(tumax);
readln;
end.
III. CÁC DẠNG BÀI TẬP THƯỜNG GẶP
1. 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. Dưới đây chúng tôi xin đưa ra một số ứng dụng kiểu xâu trong xử
lý số lớn.
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 (Đối với phép trừ 2 số nguyên thực hiện tương tự)
* Đ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)<length(s2) do
s1:='0'+s1;
while length(s2)<length(s1) do
s2:='0'+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)<length(s2) do
s1:='0'+s1;
while length(s2)<length(s1) do
s2:='0'+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;
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.
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ụ
|
Input
|
Output
|
|
2
20 004 66 |
66220004
|
|
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 là phần tử s[i] đứng trước phần từ s[j] khi (s[i] ghép với s[j])
> (s[j] ghép với s[i])
* Chương trình tham khảo
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]<s[i]+tg do inc(i);
while
tg+s[j]>s[j]+tg do dec(j);
if i<=j then
begin
if i<j then begin
k:=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.
Bài 3. Tìm số (Đề thi học
sinh giỏi tỉnh lớp 11 tỉnh Hà Tĩnh năm học 2007-2008)
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 trong tÖp Bai1.inp
KÕt qu¶: XuÊt ra mµn h×nh
|
Bai1.inp
|
KÕt qu¶
|
|
13a7b48cb7d9e68f7
|
89687
|
* Ý tưởng:
- Xóa các ký
tự chữ cái xuất hiện trong xâu
- Thực hiện xóa
các kí tự số chỉ giữ lại 5 số để tạo thành số lớn nhất bằng cách lần lượt đi
tìm 4 chữ số lớn nhất có trong xâu còn lại.
* Chương trình tham khảo:
var f,g:text;
s:string;
{=====================}
procedure
Nhap;
Begin
assign(f,'DL.INP'); reset(f);
read(f,S);
close(f);
end;
{======================}
procedure
xuly;
var
i,j,k:byte;
begin
i:=1;
repeat
if s[i] in ['0'..'9'] then inc(i)
else delete(s,i,1);
until i>length(s);
for i:=1 to 5 do
begin
k:=i;
for j:=i to length(s)+i-5 do
if s[k]<s[j] then k:=j;
if k>i then delete(s,i,k-i);
end;
writeln(copy(s,1,5));
end;
{===========================}
Begin
Nhap; xuly;
readln;
end.
Bài 4. 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 .
Ví
dụ:
|
Vào
|
Kết quả
|
|
p=3, k =11
a1=3, a2 = 4, a3 = 2
s1 = 123, s2=0, s3 = 45
|
44
|
* Ý
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.
* Chương
trình tham khảo:
{$MODE
OBJFPC}
Var A :array[1..20] of longint;
S :array[1..20] of ansistring;
st,kq :ansistring;
k,i,p,m,j
:longint;
{==============}
Procedure nhap;
Begin
st:='';
Write('Nhap p '); Readln(p);
Write('Nhap k ');Readln(k);
For i:=1 to p do readln(a[i]);
for i:=1 to p do readln(s[i]);
for i:=1 to p do
For j:=1 to A[i] do
st:=st+S[i];
End;
{===============}
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;
{===============}
BEGIN
nhap;
xuly;
Readln
END.
2. Dạng 2. 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 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 đó.
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
|
* Ý
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ự.
* Chương
trình tham khảo:
const
fi='xaugon.inp';
fo='xaugon.out';
Var s:string;f:text;
{========}
procedure doc;
begin
assign(f,fi); reset(f);
readln(f,s);
end;
{========}
procedure xuly;
var ch,kt:char;
i,max,dem:longint;
begin
assign(f,fo); rewrite(f);
i:=1;
while i<length(s) do
begin
if s[i]=s[i+1] then delete(s,i,1)
else
inc(i);
end;
writeln(f,s);
close(f);
end;
{=========}
begin
doc;
xuly;
readln;
end.
Bài 2. Nén và giải nén (Đề HSG lớp 12 tỉnh Hà Tĩnh năm
2010-2011)
Mét x©u kÝ tù
cã thÓ "nÐn" theo c¸ch sau: Mét x©u con gåm n>1 kÝ tù gièng nhau,
ch¼ng h¹n gåm n kÝ tù "a" sÏ ®îc ghi thµnh na. VÝ dô x©u 'aaaabbcd'
sÏ ®îc nÐn thµnh 4a2bcd. H·y viÕt ch¬ng tr×nh nÐn vµ gi¶i nÐn. (Chó ý trong
c¸c x©u ®îc nÐn ph¶i kh«ng cã ch÷ sè).
D÷
liÖu vµo: Cho trong tÖp string.INP
KÕt
qu¶: Ghi vµo tÖp String.Out
|
string.inp
|
string.out
|
|
aaaabbcd
3a2b
|
4a2bcd
aaabb
|
* Ý tưởng: Với việc nén xâu ta lần lượt đi
đếm các ký tự giống nhau liên tiếp trong xâu và sử dụng một xâu kq để lưu kết
quả tìm được cho đến khi xét hết xâu (việc giải nén được thực hiện ngược lại)
* Chương trình tham khảo
const fi='string.inp';
fo='string.out';
var f,g:text; s1,s2:string;
{================}
procedure doc;
begin
assign(f,fi); reset(f);
readln(f,s1);
readln(f,s2);
close(f);
end;
{================}
procedure nen;
var s,kq:string; i,d:integer; ch:char;
begin
d:=1; s1:=s1+#32;ch:=s1[1]; kq:='';
for i:=2 to length(s1) do
if s1[i]=s1[i-1] then inc(d)
else
begin
str(d,s);
if d<>1 then kq:=kq+s+ch else
kq:=kq+ch;
d:=1;
ch:=s1[i];
end;
writeln(g,kq);
end;
{================}
procedure giainen;
var s,kq,so:string;
i,j,code,n:integer; ch:char;
begin
i:=1;
kq:='';
repeat
so:='0';
while s2[i] in ['1'..'9'] do begin so:=so+s2[i];inc(i); end;
val(so,n,code);
if n>1 then
for j:=1 to n do kq:=kq+s2[i]
else kq:=kq+s2[i];
inc(i);
until i> length(s2);
writeln(g,kq);
end;
{================}
begin
assign(g,fo); rewrite(g);
doc;
nen;
giainen;
close(g);
end.
Bài 3. Ký tự khác nhau
Cho xâu s (có độ dài không vượt quá 106)
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:
- 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.
* Chương
trình tham khảo:
Var s:ansistring;
b:array['a'..'z'] of longint;
{========}
procedure nhap;
begin
write('nhap xau s:');
readln(s);
end;
{========}
procedure xuly;
var ch,kt:char; i,max,dem:longint;
begin
for 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('so luong ki tu khac
nhau:',dem);
writeln('ky tu xuat hien nhieu lan
nhat la ',kt,' so lan xh ',max);
end;
{=========}
begin
nhap;
xuly;
readln;
end.
Bài 4. Gửi thư
(nguồn http://vn.spoj.com/problems/NKLETTER)
Vị Giám đốc công ty XYZ cần gửi
một văn bản quan trọng tới một đối tác của mình. Văn bản là một xâu
S các chữ cái la tinh in thường. Để bảo mật nội dung văn bản, ông Giám
đốc gửi 2 bức thư. Bức thư thứ nhất là phần đầu Sb của xâu S, bức
thư thứ 2 là phần cuối Se của S. Hai bức thư Sb và Se đảm bảo đầy đủ
nội dung của S, tuy nhiên có thể một phần cuối của Sb có thể được
viết lặp lại trong phần đầu của Se, song số kí tự được viết lặp lại
không biết trước.
Ví
dụ: với văn bản S=’truongnguyenduquannhat’ tạo ra hai bức thư:
Sb=’truongnguyendu’ và Se=’nguyenduquannhat’
Yêu
cầu: Cho hai xâu Sb và Se, hãy xác định một xâu S có thể là nội dung
của bức thư sao cho độ dài của xâu S là ngắn nhất.
Dữ liệu
Dòng đầu chứa xâu Sb, dòng thứ hai chứa xâu Se.
Mỗi xâu có độ dài không quá 250.
Kết quả
Ghi
ra độ dài của xâu S tìm được.
Ví dụ
Dữ liệu
truongnguyendu
nguyenduquannhat
Kết quả
22
* Ý tưởng:
- Lần lượt xét các xâu con d, c tương ứng
tính từ cuối xâu s1 và đầu xâu s2, nếu d=c thì ta lưu lại độ dài của xâu d. Quá
trình cứ tiếp tục và ta nhận được độ dài xâu con chung dài nhất cần tìm (giả sử
là max).
- Kết quả bài toán là
length(s1)+length(s2) - max
* Chương trình tham khảo:
var
s,s1,d,c:string;
i,kq,n,h,k,max:integer;
begin
readln(s);
read(s1);
i:=1; h:=length(s);
k:=length(s1); n:=min(h,k); max:=0;
while i<=n do
begin
d:=copy(s,h-i+1,h);
c:=copy(s1,1,i);
if d=c then max:=i;
inc(i);
end;
write(h+k-max);
end.
3. Dạng 3. Các bài tập 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.
Bài 1. Xâu Palindrome 1
Cho
một xâu S có độ dài không vượt quá 106. Kiểm tra xem xâu S có phải
là xâu Palindrome hay không?
*
Ý tưởng: Một xâu s có tính chất đối xứng khi s[i] = s[n-i+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
{$MODE OBJFPC}
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;
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
2. 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] )
- 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 3. X©u Palindrome 3
|
xau_dx.inp
|
Xau_dx.out
|
|
edbabcd
|
2
e
c
|
Mét x©u gäi lµ ®èi xøng nÕu x©u ®ã ®äc
tõ tr¸i sang ph¶i còng gièng nh
®äc tõ ph¶i sang tr¸i. Cho mét x©u S h·y t×m sè kÝ tù Ýt nhÊt cÇn thªm vµo s©u
S ®Ó S trë thµnh x©u ®èi xøng.
D÷ liÖu vµo: xau_dx.inp gåm
Gåm mét dßng lµ x©u S
D÷ liÖu ra: Ghi vµo tÖp xau_dx.out
-
Dßng 1: §a ra sè lîng kÝ tù Ýt nhÊt cÇn chÌn thªm vµo
-
Dßng 2: C¸c kÝ tù cÇn chÌn
* ý tëng:
- Gäi S2 lµ x©u ®¶o cña x©u
S1 ban ®Çu, T lµ x©u con chung dµi nhÊt cña S1 vµ S2.
Khi ®ã c¸c kÝ tù cña S1 kh«ng thuéc T chÝnh lµ c¸c kÝ tù cÇn chÌn
vµo S1 ®Ó S1 trë thµnh x©u ®èi xøng
- Bµi to¸n trë
thµnh t×m d·y con chung dµi nhÊt cña hai d·y t¬ng øng lµ 2 x©u S1
vµ S2 b»ng ph¬ng ph¸p quy ho¹ch ®éng.
Sö
dông m¶ng L[0..max,0..max] ®Ó lu ®é dµi d·y con chung dµi nhÊt víi L[i,j] lµ
®é dµi d·y con chung dµi nhÊt cña hai d·y x©u s1 vµ s2:
Khi ®ã:
L[0,j] = 0 víi
(N = length(s1))
L[i,0] = 0 víi
(M = length(s2))
Víi
,
:
NÕu s1[i] = s2[j] th× L[i,j]:= L[i-1,j-1] + 1
ngîc l¹i L[i,j] = max{L[i-1,j], L[i,j-1]}
* Ch¬ng tr×nh tham kh¶o
program xau_doi_xung;
const maxn=100;
var L:array[0..maxn,0..maxn] of byte;
kq:array[1..maxn] of boolean;
m:integer; s1,s2:string; f:text;
{==========}
procedure doc;
var i:integer;
begin
assign(f,'daycon.inp'); reset(f);
readln(f,s1);
m:=length(s1);
s2:='';
for i:=m downto 1 do s2:=s2+s1[i];
close(f);
end;
{==========}
function max(x,y:integer):integer;
begin
if x>y then max:=x else max:=y;
end;
{===========}
procedure xuly;
var i,j:integer;
begin
fillchar(L,sizeof(L),0);
for i:=1 to m do
for j:=1 to m do
if (s1[i]=s2[j]) then
L[i,j]:=L[i-1,j-1]+1
else L[i,j]:= max(L[i-1,j], L[i,j-1]);
end;
{====================}
procedure inkq;
var i,j,d:integer;
begin
assign(f,'daycon.out'); rewrite(f);
writeln(f,m-L[m,m]);
fillchar(kq,sizeof(kq),false);
i:=m; j:=m;
while (i>0) and (j>0) do
if s1[i]=s2[j] then
begin
kq[i]:=true;
dec(i); dec(j);
end
else
if L[i,j]=L[i,j-1] then dec(j) else
dec(i);
For i:=1 to m do
if kq[i] = false then write(f,s1[i],'
');
close(f);
end;
{====================}
begin doc;
xuly; inkq; end.
Bài 4. Robot công nghiệp(Đề thi
HSG lớp 11 tỉnh Hà Tĩnh 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 hoá
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 đã 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 hoạt
động 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.
+ Chu
trình thứ ba: Đọc ký tự 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á N x 2, 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 1 số là độ
dài xâu S.
- Dòng thứ 2 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’
|
Tệp ROBOT.INP
|
Tệp ROBOT.OUT
|
|
6
|
CO
|
|
CBAABC
|
|
|
Tệp ROBOT.INP
|
Tệp ROBOT.OUT
|
|
6
|
KHONG
|
|
ACBDCA
|
|
* Ý tưởng: Với yêu cầu của đề
bài, bài toán trở thành kiểm tra xâu đầu vào có đối xứng hay không?
* Chương trình tham khảo:
var
s:ansistring;
n,i:longint;
kt:boolean;
f,g:text;
{==========}
begin
assign(f,'robot.inp'); reset(f);
assign(g,'robot.out'); rewrite(g);
readln(f,n);
readln(f,s);
kt:=true;
for i:=1 to n div 2 do
if s[i] <> s[n-i+1] then
begin
kt:=false;
break;
end;
if kt then write(g,'yes') else write(g,'no');
close(f); close(g);
end.
4. Dạng 4. 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 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.
*
Chương trình tham khảo:
{$MODE OBJFPC}
program bai1;
var
d,i,j,t:longint;s:ansistring;
a:array[1..10000]of ansistring;
{======================}
procedure
Q_sort(l,h:longint);
var
x,y:longint;k,tg:string;
begin
x:=l;
y:=h;
k:=a[(x+y)div 2];
repeat
while a[x]<k do inc(x);
while a[y]>k do dec(y);
if x<=y then
begin
tg:=a[x];
a[x]:=a[y];
a[y]:=tg;
inc(x);dec(y);
end;
until x>y;
if x<h then
Q_sort(x,h);
if y>l then
Q_sort(l,y);
end;
{=====================}
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;
{=============}
begin
xuly;
readln ;
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)
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 v¨n b¶n XAU.INP gåm:
·
Dßng ®Çu tiªn
chøa x©u S1.
·
Dßng thø hai chøa
x©u S2.
KÕt qu¶: Ghi ra tÖp v¨n
b¶n XAU.OUT:
·
ChØ mét dßng duy nhÊt ghi sè lÇn lÆp l¹i cña x©u S1 trong x©u S2.
VÝ dô:
|
XAU.INP
|
XAU.OUT
|
|
aba
bababababa
|
4
|
* Ý 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.
* Chương trình tham khảo:
{$
mode objfpc}
Var
s1,s2:ansistring;
f,g:text;
dem: longint;
begin
assign(f,'xau.inp'); reset(f);
assign(g,'xau.out'); rewrite(g);
readln(f,s1);
readln(f,s2);
dem:=0;
while (pos(s1,s2)<>0) and
(length(s2)<>0) do
begin
inc(dem);
delete(s2,pos(s1,s2),1);
end;
writeln(g,dem);
close(f); close(g);
end.
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)
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
5
3 1 3 5 2 5 3 1 3 5 2 5
|
|
6
|
* Ý 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.
* Chương trình tham khảo:
{$
mode objfpc}
Var
s1,s2,s:ansistring;
f,g:text;
dem,n,i,x: longint;
begin
assign(f,'CNKD.inp'); reset(f);
assign(g,'CNKD.out'); rewrite(g);
readln(f,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;
writeln(g,dem);
close(f); close(g);
readln;
end.
Bµi
4. Chuçi con
lín nhÊt
Cho 2 chuçi X=x1x2
...xN trong ®ã xi lµ c¸c sè tõ 0 ®Õn 9. Y=y1y2...yM trong ®ã yi
lµ c¸c sè tõ 0 ®Õn 9 vµ M, N<=250.
Gäi Z lµ chuçi con chung cña
2 chuçi X vµ Y. NÕu chuçi Z nhËn ®îc tõ chuçi X b»ng c¸ch xãa ®i mét sè kÝ tù
vµ Z còng nhËn ®îc tõ chuçi Y b»ng c¸ch xo¸ ®i mét sè kÝ tù.
Yªu cÇu: T×m mét chuçi chung
cña 2 chuçi X vµ Y sao cho chuçi nhËn ®îc t¹o thµnh mét sè lín nhÊt.
D÷
liÖu vµo: Ghi vµo tÖp ChuoiCon.INP gåm 2 dßng dßng ®Çu lµ chuçi X, dßng sau lµ
chuçi Y.
KÕt qu¶: Ghi vµo
Chuoicon.Out gåm mét dßng duy nhÊt lµ chuçi con t×m ®îc hoÆc kh«ng t×m ®îc
nÕu kh«ng cã.
|
ChuoiCon.INP
|
ChuoiCon.OUT
|
|
19012304
034012
|
34
|
* ý tëng: B»ng viÖc sö dông ph¬ng
ph¸p quy ho¹ch ®éng (®· ®îc chóng t«i tr×nh bµy trong s¸ng kiÕn kinh nghiÖm
n¨m 2010) ta sÏ t×m ®îc chuçi con chung tháa m·n ®iÒu kiÖn bµi to¸n
* Ch¬ng tr×nh:
var
L:array[0..100,0..100] of integer;
x,y,kq:string;max:integer;
{============}
procedure doc;
var
f:text; i,j:integer;
begin
assign(f,'bai4.inp');reset(f); readln(f,x);
readln(f,y); close(f);
end;
{==============}
procedure xuli1;
var
i,j,m,n:byte;
begin
m:=length(x);n:=length(y);
for i:=1 to m do
for j:=1 to n do
if x[i]=y[j] then L[i,j]:=L[i-1,j-1]+1
else
if L[i-1,j]>L[i,j-1] then
L[i,j]:=L[i-1,j] else L[i,j]:=L[i,j-1];
max:=L[m,n]; writeln(max);
end;
{=============}
procedure in_kq;
var i,j,is,js,so:byte; ch:char;
begin
Is:=length(x);Js:=length(y);so:=0;
repeat
for ch:='9' downto '0' do
begin
i:=is; j:=js;
while (x[i]<>ch) and(i>0)
do dec(i);
while (y[j]<>ch) and(j>0)
do dec(j);
if L[i,j]=max-so then
begin kq:=ch+kq; Is:=i; Js:=j; break; end;
end;
inc(so);
until max=so;
write(kq);
end;
{=================}
begin doc;
kq:=' '; xuli1; in_kq; readln; end.
IV. BÀI TẬP ÁP DỤNG
Bài 1. chuỗi đối xứng (nguồn http://vn.spoj.com/submit/NKPALIN)
Một chuỗi được gọi là đối xứng
(palindrome) nếu như khi đọc chuỗi này từ phải sang trái cũng thu được chuỗi
ban đầu.
Yêu cầu: tìm một chuỗi con đối xứng
dài nhất của một chuỗi s cho trước. Chuỗi con là chuỗi thu được khi xóa đi một
số ký tự từ chuỗi ban đầu.
Dữ liệu vào
Gồm
một dòng duy nhất chứa chuỗi s, chỉ gồm những chữ cái in thường.
Kết quả
Gồm
một dòng duy nhất là một xâu con đối xứng dài nhất của xâu s. Nếu có nhiều kết
quả, chỉ cần in ra một kết quả bất kỳ.
Giới hạn
Chuỗi
s có độ dài không vượt quá 2000.
Ví dụ
Dữ liệu mẫu
lmevxeyzl
Kết qủa
level
program
NKPALIN;
var
s1,s2:ansistring;
L:array[0..2000,0..2000] of integer;
n:integer;
{-------------}
procedure nhap;
var ii:integer;
begin
read(s1);
n:=length(s1);
for
ii:=n downto 1 do s2:=s2+S1[ii];
for
ii:=1 to n do begin L[0,ii]:=0; L[ii,0]:=0; end;
end;
{-------------}
function
max(x,y:integer):integer;
begin
if x>y then max:=x else max:=y;
end;
{-------------}
procedure
tim;
var i,j,k:integer;
begin
for i:=1 to n do
for j:=1 to n do
if s1[i]=s2[j] then l[i,j]:=l[i-1,j-1]+1
else l[i,j]:=max(l[i,j-1],l[i-1,j]);
end;
{--------------}
procedure
trace;
var i,j,x:integer;
kq:ansistring;
begin
kq:='';
i:=n; j:=n;
x:= 0;
while (i>0) and (j>0) do
begin
if s1[i]=s2[j] then
begin
inc(x);
kq:=kq+s1[i];
dec(i);
dec(j);
end
else if l[i,j]=l[i,j-1] then dec(j)
else dec(i);
end;
for i:=x downto 1 do write(kq[i]);
end;
{---------------}
begin
nhap; tim; trace; end.
Bài 2. 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)
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
abcd abc
|
acb
abc abcd abcde
|
var a: array[0..21]
of string;
s:ansistring;
i,n:longint;
f,g:text;
{===================}
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;
inc(dem);
a[dem]:=x;
n:=dem;
end;
{===================}
procedure qsort(L,H:
word);
var tg,k:ansistring;
i,j:longint;
begin
if l>=h then
exit;
i:=l; j:=h;
tg:=a[(l+h) div 2];
repeat
while
length(a[i])<length(tg) do inc(i);
while
length(a[j])>length(tg) do dec(j);
if i<=j then
begin
if i<j then begin
k:=a[i];
a[i]:=a[j];
a[j]:=k;
end;
inc(i);dec(j);
end;
until i>j;
Qsort(l,j);Qsort(i,h);
end;
{=================}
begin
assign(f,'sapxau.inp'); reset(f);
assign(g,'sapxau.out'); rewrite(g);
readln(f,s);
tachtu;
qsort(1,n);
for i:=1 to n do write(g,a[i],' ');
close(f); close(g);
end.
Bài
3. 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.INP
|
SAPXEP.OUT
|
|
3
abc1x2y3z
cb1
1cd7hd
|
cb1
1cd7hd
abc1x2y3z
|
var
s: array[0..1000] of ansistring;
i,n:longint;
f,g:text;
{===================}
function dem_so(x:ansistring):longint;
begin
dem_So:=0;
for i:=1 to length(x) do
if x[i] in ['0'..'9'] then inc(dem_so);
end;
{===================}
procedure
qsort(L,H: word);
var
tg,k:ansistring; i,j:longint;
begin
if
l>=h then exit;
i:=l; j:=h; tg:=s[(l+h) div 2];
repeat
while
dem_so(s[i])<dem_so(tg) do inc(i);
while
dem_so(s[j])>dem_so(tg) do dec(j);
if
i<=j then
begin
if i<j then begin k:=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
assign(f,'sapxep.inp'); reset(f);
assign(g,'sapxep.out'); rewrite(g);
readln(f,n);
for i:=1 to n do readln(f,s[i]);
qsort(1,n);
for i:=1 to n do writeln(g,s[i]);
close(f); close(g);
end.
Bài 4. Chữ cái xuất hiện (Đề
thi học sinh giỏi lớp 12 tỉnh Thanh Hóa năm 2011-2012)
Cho
xâu st chỉ gồm các chữ cái. Tính số lần xuất hiện của chữ cái xuất hiện nhiều
lần nhất trong xâu (không phân biệt chữ hoa và chữ thường)
Dữ liệu vào: Từ tệp bai3.inp là
xâu st có độ dài không quá 500
Dữ liệu ra: Ghi vào tệp bai3.out
một dòng duy nhất là bội chung nhỏ nhất của kết quả bài toán với 105
Ví dụ:
|
Bai3.inp
|
Bai3.out
|
|
AAABDA
|
100000
|
Var s:ansistring;
b:array['A'..'Z'] of integer;
f,g:text;
{========}
procedure nhap;
begin
assign(f,'bai3.inp'); reset(f);
readln(f,s);
close(f);
end;
{========}
function BCNN(x,y:longint):longint;
var i:integer;
begin
Y:=100000;i:=1;
IF Y MOD X = 0 THEN bcnn:=Y
else
while i*y mod x <> 0 do inc(i);
BCNN:=i*y;
end;
{========}
procedure xuly;
var k,ch:char; i,max,dem:longint;
begin
assign(g,'bai3.out'); rewrite(g);
for ch:='A' to 'Z' do b[ch]:=0;
for i:=1 to length(s) do
begin
k:=upcase(s[i]);
inc(b[k]);
end;
max:=0;
for ch:='A' to 'Z' do
if b[ch]>max then
max:=b[ch];
writeln(g,BCNN(max,100000));
close(g);
end;
{=========}
begin nhap;
xuly; readln; end.
Bài
5. Xâu chung (Đề thi học sinh giỏi lớp 12 tỉnh Nghệ An 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
|
Bai2.inp
|
|
Ky thi hoc sinh gioi Tinh mon tin hoc
hoc sinh gioi mon Tin hoc
|
14
|
const
fi='bai2.inp';
fo='bai2.out';
var s1,s2:string;
max:integer;
f:text;
{===============}
procedure doc;
begin
assign(f,fi); reset(f);
readln(f,s1);
readln(f,s2);
close(f);
end;
{===============}
procedure xuly;
var kq:string; i,j:integer;
begin
assign(f,fo); rewrite(f);
max:=0;
for i:=1 to length(s1) do
for j:=1 to length(s1) do
begin
kq:=copy(s1,i,j-i+1);
if pos(kq,s2)<>0 then
if max<j-i+1 then max:=j-i+1;
end;
writeln(f,max);
close(f);
end;
{==============}
begin doc;
xuly; end.
Bài
6. 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)
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 mền
Cô
nàng cất rượu ủ thêm men .
( trích hoa và rượu của - Nguyễn Bính)
|
Thấy
rét u tôi bọc lại mền
Cô
nàng cất rượu ủ thêm men .
(trích
hoa và rượu của - Nguyễn Bính)
|
const
fi='bai3.inp';
fo='bai3.out';
var
f,g:text;
st:array[1..1000] of ansistring;
n,i:longint;
{=================}
procedure doc;
var
dem,i:longint;
begin
assign(f,fi);
reset(f);
dem:=0;
while not eof(f) do
begin
inc(dem);
readln(f,st[dem]);
end;
n:=dem;
close(f);
end;
{================}
procedure chuanhoa(var x:ansistring);
var
dau:string; vt:longint; s:ansistring;
begin
s:=x;
while s[1]=' ' do delete(s,1,1);
while s[length(s)]=' ' do
delete(s,length(s),1);
while pos(' ',s)<>0 do
begin
vt:=pos('
',s);
delete(s,vt,1);
end;
dau:=' .';
while pos(dau,s)<>0 do delete(s,pos(dau,s),1);
dau:='.';
while (pos(dau,s)>0) and
(pos(dau,s)<length(s)) and (s[pos(dau,s)+1]<>' ')do insert('
',s,pos(dau,s)+1);
dau:=' ;';
while
pos(dau,s)<>0 do delete(s,pos(dau,s),1);
dau:=';';
while (pos(dau,s)>0) and
(pos(dau,s)<length(s)) and (s[pos(dau,s)+1]<>' ')do insert('
',s,pos(dau,s)+1);
dau:=' ?';
while
pos(dau,s)<>0 do delete(s,pos(dau,s),1);
dau:='?';
while (pos(dau,s)>0) and
(pos(dau,s)<length(s)) and (s[pos(dau,s)+1]<>' ')do insert('
',s,pos(dau,s)+1);
dau:=' !';
while
pos(dau,s)<>0 do delete(s,pos(dau,s),1);
dau:='!';
while (pos(dau,s)>0) and
(pos(dau,s)<length(s)) and (s[pos(dau,s)+1]<>' ')do insert('
',s,pos(dau,s)+1);
dau:=' )';
while
pos(dau,s)<>0 do delete(s,pos(dau,s),1);
dau:='( ';
while
pos(dau,s)<>0 do delete(s,pos(dau,s)+1,1);
x:=s;
x:=s;
end;
{================}
begin
doc;
assign(g,fo); rewrite(g);
for i:=1 to n do
begin
chuanhoa(st[i]);
writeln(g,st[i]);
end;
close(g);
readln;
end.
Bài 7. Tìm từ
(Đề thi học sinh giỏi lớp 12 tỉnh Bạc Liêu năm 2011-2012)
Cho xâu khác rỗng. Tìm từ đầu tiên dài
nhất trong xâu (Từ là một dãy liên tiếp không có dấu cách)
Dữ liệu vào: Từ tệp cau2.inp gồm một
dòng duy nhất
Dữ liệu ra: Ghi vào tệp cau2.out gồm một
dòng là từ tìm được
|
Cau2.inp
|
Cau2.out
|
|
Hoc
tin rat thu vi
|
Hoc
|
const fi='cau.inp';
fo='cau.out';
var s:ansistring;
max:integer;
f:text;
{===============}
procedure doc;
begin
assign(f,fi); reset(f);
readln(f,s);
close(f);
end;
{===============}
procedure xuly;
var kq,max,s1:ansistring; vt:longint;
begin
assign(f,fo); rewrite(f);
s1:=s;
max:='';
while (pos(' ',s1)<> 0) and
(length(s1)>0) do
begin
vt:=pos(' ',s1);
kq:=copy(s1,1,vt-1);
delete(s1,1,vt);
if length(kq)>length(max) then max:=kq;
end;
writeln(f,max);
close(f);
end;
{==============}
begin doc;
xuly; end.
Bài 8. Liệt kê chữ cái (đề thi học sinh giỏi lớp 12 năm học 2011-2012 tỉnh
Bạc Liêu)
Cho một văn bản chứa trong một
tệp văn bản. 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: Tệp Dem_chu.inp gồm nhiều
dòng chứa các ký tự trong tệp
Dữ liệu ra: Tệp Dem_chu.out gồm nhiều
dòng ghi các ký tự xuất hiện một lần.
|
Dem_chu.inp
|
Dem_chu.out
|
|
NAM MOI HANH PHUC
|
C
I
O
P
U
|
const fi='dem_chu.inp';
fo='dem_chu.out';
var s:ansistring;
b:array['A'..'Z'] of
longint;
f,g:text;
i:longint; ch:char;
{===============}
begin
assign(f,fi); reset(f);
assign(g,fo); rewrite(g);
fillchar(b,sizeof(b),0);
While not eof(f) do
begin
readln(f,s);
for i:=1 to length(s) do
if s[i]<>' ' then inc(b[upcase(s[i])]);
end;
for ch:='A' to 'Z' do
if b[ch]=1 then writeln(g,ch);
close(f); close(g);
end.
Bài 9. Tìm số (đề thi học sinh giỏi lớp 12 bảng A năm học
2011-2012 tỉnh Bạc Liêu)
Cho xâu s gồm ít nhất 3 kí tự số. Xóa
bỏ một số kí tự trong xâu s chỉ để lại 3 kí tự số sao cho vân giữ nguyên thứ tự
của chúng tạo nên số có giá trị lớn nhất.
Dữ liệu vào: Từ tệp cau2.inp gồm 1
dòng chứa xâu s
Dữ liệu ra: ghi vao tệp cau2.out xâu s
chứa 3 kí tự số còn lại tạo thành số lớn nhất
|
cau2.inp
|
cau.out
|
|
124512hoctin8126123
|
863
|
var f,g:text;
s:string;
{=====================}
procedure Nhap;
Begin
assign(f,'cau2.inp'); reset(f);
read(f,S);
close(f);
end;
{======================}
procedure xuly;
var i,j,k:byte;
begin
i:=1;
repeat
if s[i] in ['0'..'9'] then inc(i)
else delete(s,i,1);
until i>length(s);
for i:=1 to 3 do
begin
k:=i;
for j:=i to length(s)+i-3 do
if s[k]<s[j] then k:=j;
if k>i then delete(s,i,k-i);
end;
assign(f,'cau2.out'); rewrite(f);
writeln(f,copy(s,1,3));
close(f);
end;
{===========================}
Begin Nhap;
xuly; readln; end.
Bài 10. Siêu đối xứng
(http://vn.spoj.com/problems/NKSP)
Một xâu có độ dài lớn hơn 1 chỉ
gồm các chữ cái la tinh in thường được gọi là đối xứng, nếu ta đọc xâu
đó từ trái sang phải và từ phải sang trái là như nhau. Một xâu được gọi
là siêu đối xứng, nếu nó là xâu đối xứng hoặc được tạo thành bằng cách ghép
liên tiếp từ nhiều xâu đối xứng.
Yêu
cầu: Cho một xâu S, hãy đếm số xâu con siêu đối xứng của S.( Xâu con của một
xâu S là một đoạn liên tiếp các ký tự của S)
Dữ liệu
Chứa
xâu S với độ dài không vượt quá 1000.
Kết quả
Ghi
ra số xâu con tìm được.
Ví dụ
Dữ liệu
abc
Kết quả
0
Dữ liệu
abacdc
Kết quả
3
const fi='';
var
s:ansistring;
f:text;
A:array[1..1000,1..1000] of boolean;
kq,i,j,k,n:longint;
{=============}
function
kt(x,y:longint):boolean;
var
u,h:longint;
begin
h:=(y-x) shr 1;
for
u:=0 to h do
if S[x+u]<>S[y-u] then exit(false);
exit(true);
end;
{=============}
begin
assign(f,fi); reset(f);
read(f,s);
close(f);
kq:=0;
n:=length(s);
for i:=1 to n-1 do
for j:=i+1 to n do
if kt(i,j) then A[i,j]:=true
else
A[i,j]:=false;
for i:=1 to
n-3 do
for j:=i+3
to n do
for
k:=i+1 to j-2 do
if (A[i,k])and(A[k+1,j]) then begin
A[i,j]:=true;break;end;
for
i:=1 to n-1 do
for j:=i+1
to n do
if
A[i,j] then inc(kq);
write(kq);
end.
Bài 11. Writing (Nguồn http://vn.spoj.com/submit/PBCWRI)
Cho
2 chuỗi A,B chứa các chữ cái trong bảng chữ tiếng Anh (có cả chữ hoa và chữ
thường). Chuỗi A có độ dài n, chuỗi B có độ dài m.
Yêu
cầu: Đếm số lần xuất hiện của các hoán vị
của chuỗi A trong chuỗi B.
Dữ liệu
- Dòng đầu tiên chứa
2 số nguyên n và m.
- Dòng thứ 2 chứa n kí tự của chuỗi A.
- Dòng thứ 3 chứa m kí tự của chuỗi B.
Kết qủa
- Một số duy nhất là
kết quả của bài toán.
Giới hạn
- n ≤ 3000
- m ≤ 3 000 000
Ví dụ
Dữ liệu
4 11
cAda
AbrAcadAbRa
Kết quả
2
Giải
thích: 2 lần bắt đầu từ vị trí 4 và 5.
Const fi='PBCWRI.INP';
fo='PBCWRI.OUT';
Var B:array[1..3000001] Of Char;
D1,D2:array['a'..'z'] Of Longint;
C1,C2:array['A'..'Z'] Of Longint;
n,m,kq,i,x:Longint;
h:char;
f,g:text;
Begin
assign(f,fi); reset(f);
assign(g,fo); rewrite(g);
Readln(f,n,m);
If
m<n then
Begin
Write(0);
Exit;
End;
kq:=0;
Fillchar(D1,Sizeof(D1),0);
Fillchar(C1,Sizeof(C1),0);
D2:=D1;
C2:=C1;
For i:=1 to n do
Begin
Read(f,h);
If (h>='a') And (h<='z') then Inc(D1[h])
Else Inc(C1[h]);
End;
Readln;
For
i:=1 to n-1 do
Begin
Read(f,B[i]);
If (B[i]>='a') And (B[i]<='z') then Inc(D2[B[i]])
Else Inc(C2[B[i]]);
End;
For
i:=n to m do
Begin
Read(f,B[i]);
If (B[i]>='a') And (B[i]<='z') then Inc(D2[B[i]])
Else Inc(C2[B[i]]);
x:=0;
For h:='a' to 'z' do
If D2[h]<>D1[h] then x:=1;
If x=0 then
For h:='A' to 'Z' do
If C1[h]<>C2[h] then x:=1;
If x=0 then Inc(kq);
x:=i-n+1;
If (B[x]>='a') And (B[x]<='z') then Dec(D2[B[x]])
Else Dec(C2[B[x]]);
End;
Write(g,kq);
close(f); close(g);
End.
Bài 12. Tìm
mật khẩu (Đề thi chọn đội tuyển dự thi HSG Quốc gia năm
2012-2013)
Việc bảo vệ máy tính của mình để hạn
chế người khác thâm nhập vào là một vấn
đề đặt ra cho mọi nguời sử dụng máy tính. Để tăng tính an toàn trong lưu trữ, một
nguời đã quyết định dấu mật khẩu truy cập máy tính của mình vào một xâu T với một
quy ước sao cho khi cần anh ta có thể lấy lại đuợc mật khẩu từ T như sau:
Là một người yêu thích số học anh ta
thường chọn mật khẩu P là một số nguyên tố và đem dấu vào một xâu ký tự T sao
cho P chính là số nguyên tố có giá trị lớn nhất trong số các số nguyên tố tạo
được từ các xâu con của T (xâu con của một xâu ký tự T là một chuỗi liên tiếp
các ký tự trong T).
Ví
dụ: xâu T= “timpassword232432fsdgd45435dsfdsf” chứa mật khẩu là 43 vì T chứa
các xâu con ứng với các số nguyên tố 2, 3, 23, 43, và 5.
Yêu cầu:
Cho một xâu ký tự T chiều dài không quá 250 ký tự. Tìm mật khẩu P đã dấu trong
xâu T biết P có giá trị nhỏ hơn 105. Dữ liệu cho đảm bảo T chứa ít
nhất 1 số nguyên tố.
Dữ liệu:
Vào từ file văn bản PASSWORD.INP gồm 1 dòng duy nhất là xâu T.
Kết quả:
Ghi ra file văn bản PASSWORD.OUT chứa số P tìm được.
Ví
dụ:
|
PASSWORD.INP
|
PASSWORD.OUT
|
|
timpassword232432fsdgd45435dsfdsf
|
43
|
const fi='password.inp';
fo='password.out';
var
f:text; s:ansistring; max:int64;
{=================}
procedure doc;
begin
assign(f,fi); reset(f);
readln(f,s);
close(f);
end;
{=================}
function kiemtra(v:int64):boolean;
var
i:longint;
begin
if v<=1 then exit(false);
for i:=2 to trunc(sqrt(v)) do
if v mod i = 0 then exit(false);
exit(true);
end;
{=================}
procedure xuly;
var i,j:longint; v:int64;
begin
v:=0;max:=0;
for i:=1 to length(s) do
begin
j:=i; v:=0;
while (j<=length(s)) do
begin
if (s[j]<'1') or
(s[j]>'9') then break;
v:=v*10+ ord(s[j]) - ord('0');
if kiemtra(v) and (v>max)
then max:=v;
if v>100000 then break;
inc(j);
end;
end;
assign(f,fo); rewrite(f);
write(f,max);
close(f);
end;
{=================}
begin
doc;
xuly;
end.
Bài 13. Biến đổi xâu ký tự (Đề thi chọn đội tuyển dự thi học
sinh giỏi Quốc Gia lớp 12 năm học 2010-2011)
Cho
n xâu ký tự A1A2...An(n£100). Mỗi xâu không quá 10 ký tự.
Với một xâu s cho trước, hãy tìm tất cả các cách biểu diễn s dưới dạng ghép các
xâu ký tự Ai, mỗi xâu ký tự Ai có thể xuất hiện trong một
cách biểu diễn nào đó nhiều lần.
Dữ
liệu vào: Tệp xau.inp có cấu trúc:
-
Dòng đầu ghi xâu s
-
Dòng 2 ghi số n
-
N dòng tiếp theo, dòng i ghi xâu Ai
Dữ
liệu ra: Ghi vào tệp xau.out có cấu trúc:
-
Nếu không có cách nào biểu diễn thì ghi không có
-
Nếu có thì ghi mỗi cách trên một dòng theo ví dụ dưới đây
|
xau.INP
|
xau.OUT
|
|
abacd
6
ab
cd
a
b
c
d
|
A[1]A[3]A[2]
A[1]A[3]A[5]A[6]
A[3]A[4]A[3]A[2]
A[3]A[4]A[3]A[5]A[6]
|
const fi='xau.inp';
fo='xau.out';
var f:text;
s,s3,xau,tg:ansistring;
n,max,dem,m1,m2:integer;
a,b:array[1..100] of string;
kq:array[1..100] of integer;
{=================}
procedure doc;
var i:integer;
begin
assign(f,fi);
reset(f);
readln(f,s);
readln(f,n);
for i:=1 to n do readln(f,a[i]);
close(f);
end;
{================}
function kiemtra(max:integer):boolean;
var
s1:ansistring; t:integer;
begin
s1:='';
for t:=1 to max do
begin
s1:=s1+a[kq[t]];
if s1=s then exit(true);
end;
exit(false);
end;
{================}
procedure result;
var
t,j:integer; s1,xau1,xau:ansistring;
begin
s1:='';
for t:=1 to max do
begin
s1:=s1+a[kq[t]];
if s1=s then
begin
for j:=1 to t do begin str(kq[j],xau1);
xau:=xau+'a['+xau1+']'; end;
inc(dem);
b[dem]:=xau;
exit;
end;
end;
end;
{================}
procedure try(i:integer);
var j:integer;
begin
if i<=length(s) then
for j:=1 to n do
begin
kq[i]:=j;
str(j,xau);
if kiemtra(i) then begin max:=i;
result; end;
try(i+1);
end;
end;
{================}
procedure xuly;
begin
assign(f,fo); rewrite(f);
IF dem=0 then write(f,'khong co')
else
begin
for m1:=1 to dem-1 do
for m2:=m1+1 to dem do
if
length(b[m1])>length(b[m2]) then
begin
tg:=b[m1]; b[m1]:=b[m2]; b[m2]:=tg;
end;
for
m1:=1 to dem-1 do
for m2:=m1+1 to dem do
if
b[m1]>b[m2] then
begin
tg:=b[m1]; b[m1]:=b[m2]; b[m2]:=tg;
end;
writeln(f,b[1]);
for m1:=2 to dem do
if b[m1]<>b[m1-1] then
writeln(f,b[m1]);
end;
close(f);
end;
{=========}
begin
doc;
try(1);
xuly;
end.
Bài 14. Ghép xâu (Đề
thi giáo viên dạy giỏi bậc THPT chu kỳ 2011-2015 Tỉnh Nghệ An)
Cho 2 xâu ký tự S1, S2.
Có thể ghép một số lần liên tiếp xâu S1 để được xâu S2
hay không?
Dữ liệu: Vào từ tệp Xau.inp
-
Dòng 1. Ghi xâu S1
-
Dòng 2: Ghi xâu S2
Kết quả: Ghi vào tệp Xau.out số K
là số lần ghép liên tiếp xâu S1 để được xâu S2, trường
hợp ngược lại ghi số 0.
|
xau.INP
|
xau.OUT
|
|
ACM
ACMACMACM
|
3
|
const fi='xau.inp';
fo='xau.out';
var
s1,s2,s:ansistring;
i,dem:longint;
f,g:text;
{==========}
begin
assign(f,'xau.inp'); reset(f);
assign(g,'xau.out'); rewrite(g);
readln(f,s1);
readln(f,s2);
s:=s2; dem:=0;
while (length(s)>0) and
(pos(s1,s)<>0) do
begin
inc(dem);
delete(s,pos(s1,s),length(s1));
end;
if length(s)<>0 then write(g,0) else
write(g,dem);
close(f); close(g);
end.
Bài 15.
Tiền tố và hậu tố (http://vn.spoj.com/problems/C11STR2/)
Xâu a được gọi là tiền tố của
xâu b nếu xâu a trùng với phần đầu của xâu b. Ví dụ pre là tiền
tố củaprefix
Xâu a được gọi là hậu tố của
xâu b nếu xâu a trùng với phần cuối của xâu b. Ví dụ fix là hậu
tố củasuffix
yenthanh132 vừa
mới học về tiền tố và hậu tố nên hôm nay anh ta sẽ đố các bạn một bài toán đơn
giản về tiền tố và hậu tố như sau:
- Cho 2 xâu a,b gồm
các kí tự latin thường ('a' đến 'z')
- Tìm 1 xâu c thỏa
mãn:
1.
Xâu a là
tiền tố của xâu c
2.
Xâu b là hậu
tố của xâu c
3.
Độ xài xâu
c là ngắn nhất.
Input
- Dòng 1: Xâu a
- Dòng 2: Xâu b
Output
- Một dòng duy nhất
là xâu c.
Giới
hạn:
- 40% số test có độ
dài 2 xâu a,b <= 1000 kí tự
- Trong toàn bộ test,
độ dài 2 xâu a,b <= 105 kí tự
Ví dụ:
Input 1:
abca
cab
Output 1:
cab
Output 1:
abcab
Input 2:
Input 2:
abc
abc
Output 2:
abc
Output 2:
abc
(2 xâu a,b không nhất thiết phải khác nhau).
(2 xâu a,b không nhất thiết phải khác nhau).
var
a,b,d,c:string;
i,kq,n,h,k,max:integer;
begin
readln(a);
read(b);
i:=1; h:=length(a);
k:=length(b);
max:=0;
if h>k then n:=h else n:=k;
while i<=n do
begin
d:=copy(a,h-i+1,h);
c:=copy(b,1,i);
if d=c then max:=i;
inc(i);
end;
delete(b,1,max);
c:=a+b;
write(c);
readln;
end.
* Một số bài tập kiểu dữ liệu xâu học
sinh trong đội tuyển Quốc gia có thể luyện tập trực tuyến trên trang spoj là:
- OR xâu (http://vn.spoj.com/submit/MNE07)
- Tên đẹp (http://vn.spoj.com/problems/C11BEAU)
- Substring (http://vn.spoj.com/problems/DIFFSTR/)
- Tách từ (http://vn.spoj.com/submit/NKH)
-
Xâu đối xứng (Nguồn http://vn.spoj.com/problems/PALINX/)
PhÇn C. KÕt luËn vµ kiÕn nghÞ
KÕt luËn
Víi
môc ®Ých ®Æt ra ®Ò tµi ®· lµm ®îc:
- Giíi thiÖu c¸ch khai b¸o vµ truy xuÊt kiÓu
d÷ liÖu x©u (®Æc biÖt lµ ansistring)
- Giíi thiÖu
c¸c hµm, thñ tôc trªn kiÓu d÷ liÖu x©u
- §Æc biÖt
trong qu¸ tr×nh båi dìng häc sinh giái chóng t«i ®· ®óc rót vµ ph©n tÝch thµnh
mét sè d¹ng bµi tËp c¬ b¶n gióp cho häc sinh luyÖn tËp vµ øng dông vµo bµi tËp
cô thÓ.
Qua c¸c néi dung ®îc tr×nh bµy, hy väng gi¸o viªn Tin häc còng nh c¸c em häc sinh ¸p
dông ®îc phÇn nµo trong qu¸ tr×nh båi dìng häc sinh giái c¸c cÊp. Chóng t«i
mong nhËn ®îc nhiÒu ý kiÕn ®ãng gãp tõ quý thÇy c« vµ c¸c ®ång nghiÖp ®Ó cµng
hoµn thiÖn h¬n.
Bµi viÕt ®îc
hoµn thµnh ngoµi sù cè g¾ng nç lùc cña b¶n th©n, cßn cã sù gióp ®ì rÊt lín vµ
tËn t×nh cña Ban gi¸m hiÖu, c¸c ®ång nghiÖp trong c¬ quan vµ mét sè gi¸o viªn
Tin häc tham gia gi¶ng d¹y t¹i c¸c trêng phæ th«ng.
KiÕn nghÞ
"Chuyªn ®Ò båi dìng kiÓu d÷
liÖu x©u" ®·
giíi thiÖu mét sè d¹ng bµi tËp c¬ b¶n trªn c¬ së tËp hîp mét sè ®Ò thi häc sinh
giái c¸c tØnh, ®Ò thi chän ®éi tuyÓn dù thi häc sinh giái Quèc gia ®Ó ¸p dông
vµo bµi to¸n nµo ®ã, tríc hÕt cÇn nghiªn cøu kÜ c¸c thao t¸c xö lý trªn x©u vµ
nhËn d¹ng ®Ò ®Ó vËn dông vµo d¹ng bµi to¸n phï hîp.
"Chuyªn ®Ò båi dìng kiÓu d÷
liÖu x©u"
lµ tµi liÖu gi¶ng d¹y tèt cho gi¸o viªn trong båi dìng häc sinh giái c¸c cÊp vµ
¸p dông tèt ®èi víi ®èi tîng häc sinh ®· häc qua tin pascal c¬ së.
S¸ng kiÕn kinh nghiÖm nµy cã thÓ më réng b»ng
c¸ch bæ sung thªm c¸c d¹ng to¸n thêng gÆp vµ tiÕn tíi viÖc giíi thiÖu c¸c ®Ò
thi häc sinh giái c¸c cÊp kÌm theo lêi gi¶i tõ ®ã lËp thµnh menu gióp häc sinh
häc tËp thuËn tiÖn h¬n.
Tµi liÖu tham kh¶o
1. NguyÔn T« Thµnh, LËp tr×nh n©ng cao trªn ng«n ng÷ Pascal. NXB §¹i häc Quèc
gia Hµ Néi - N¨m 2000
2. TrÇn §øc Huyªn, ph¬ng ph¸p gi¶i c¸c bµi to¸n trong Tin häc.
NXB
Gi¸o dôc - N¨m 1997
3.
S¸ch gi¸o khoa Tin häc 11. NXB Gi¸o dôc - N¨m 2004
4.
Hå SÜ §µm. Tµi liÖu gi¸o khoa chuyªn Tin 1, 2, 3. NXB Gi¸o dôc -
N¨m 2009
5. Trang vn.spoj.com
Môc
lôc
PhÇn A - §Æt vÊn ®Ò.............................................................................. 1
I
- C¬ së khoa häc vµ c¬ së thùc tiÔn trong viÖc chän ®Ò tµi.................. 1
II
- Môc ®Ých, nhiÖm vô cña viÖc thùc hiÖn ®Ò tµi nghiªn cøu............... 1
III
- §èi tîng, thêi gian vµ ph¬ng ph¸p nghiªn cøu.......................... 2
1.
§èi tîng nghiªn cøu................................................................ 2
2.
Thêi gian nghiªn cøu ®Ò tµi........................................................ 2
3.
Ph¬ng ph¸p nghiªn cøu ®Ò tµi................................................... 2
PhÇn B - Néi dung................................................................................. 3
I. C¸ch khai
b¸o vµ truy xuÊt ®Õn phÇn tö x©u...................................... 3
1. C¸ch khai b¸o............................................................................ 3
2. C¸ch nhËp/xuÊt........................................................................... 3
3. Truy
cËp ®Õn tõng phÇn tö m¶ng................................................ 3
II. C¸c thao
t¸c trªn x©u....................................................................... 3
1. PhÐp céng x©u............................................................................ 3
2. PhÐp so s¸nh............................................................................... 4
3. C¸c thñ tôc vµ hµm chuÈn xö
lý trªn x©u ký tù........................... 4
III. Mét sè d¹ng bµi to¸n
thêng gÆp................................................... 8
D¹ng 1. Xö lý sè nguyªn lín.......................................................... 8
D¹ng 2. BiÕn ®æi x©u.................................................................... 15
D¹ng
3. C¸c bµi tËp x©u Palindrome.............................................. 20
D¹ng 4.
T×m x©u con .................................................................... 26
IV. Bµi tËp ¸p dông............................................................................ 33
PhÇn C - KÕt luËn vµ kiÕn NghÞ.......................................................... 58
Tµi liÖu tham kh¶o............................................................................... 59
Mình đã dành 2 ngày để làm hết các đề của bạn. Các bài tập rất hay.
Trả lờiXóabạn chạy chương trình bài tìm số xem có đúng ko ạ
XóaAnh cho em hỏi? Thực hiện phép tính trên xâu có ứng dụng trong thực tế hay không hay là thử thách trí tuệ của học sinh thôi. Trong khi thực hiên phép tính +,-,*,/ trên các kiểu số đã làm rất tốt.
Trả lờiXóaPHÉP TOÁN TRÊN XÂU VỚI SÔ LỚN LÀ SỐ CÓ KHOẢNG 200 CHỨ SÔ CƠ MÀ BÁC
Xóamình chạy thử các bài tìm số đều cho kết quả ko đúng
Trả lờiXóa