Ai biết ý tưởng giải thuật của bài này như thế nào giúp minh với

HTML:
Ví dụ 6. Cho xâu s (ñộ dài không vượt quá 10^6  chỉ gồm 2 kí tự 'A' và 'B'. đếm số cách chọn cặp chỉ số (i,j) mà xâu con liên tiếp từ kí tự thứ i ñến kí tự thứ j của xâu s có số lượng kí tự 'A' bằng số lượng kí tự 'B'.
Dữ liệu vào trong file “AB.INP” có dạng:
gồm một dòng duy nhất chứa xâu s
Kết quả ra file “AB.OUT”
có dạng:gồm một dòng duy nhất chứa một số là kết quả bài toán.
AB.INP                          AB.OUT
ABAB                            4
 
const MAX =1000000;
fi ='AB.INP';
fo ='AB.OUT';
var s :ansistring;
c :array[-MAX..MAX]of longint;
f :text;
i, sum :longint;
count :int64;
BEGIN
assign(f,fi); reset(f);
read(f,s);
close(f);
fillchar(c,sizeof(c),0);
c[0]:=1;
sum:=0;
count:=0;
for i:=1 to length(s) do begin
if s[i]='A' then sum:=sum - 1
else sum:=sum + 1;
count:=count + c[sum];
inc(c[sum]);
end;
assign(f,fo); rewrite(f);
write(f,count);
close(f);
END.
Bài tập
 

tengiday

Happy life
Bạn thử nghĩ như thế này xem:
Với i <= j, gọi:
Mã:
a[i..j] = số lượng 'A' trong đoạn [i..j],
b[i..j] = số lượng 'B' trong đoạn [i..j].
Như vậy,
Mã:
a[i..j] = a[1..j] - a[1..i-1],
b[i..j] = b[1..j] - b[1..i-1].
Nếu đoạn [i, j] thỏa mãn số lượng 'A' bằng số lượng 'B', thì ta phải có: a[i..j] = b[i..j]. Thay thế theo như trên, ta có:
Mã:
a[1..j] - b[1..j] = a[1..i-1] - b[1..i-1].
Công thức trên có nghĩa rằng: đoạn [i, j] thỏa mãn tính chất như đề bài khi và chỉ khi
Mã:
sự khác nhau (hiệu) của số lượng 'A' và 'B' trong đoạn [1..j] = sự khác nhau (hiệu) của số lượng 'A' và 'B' trong đoạn [1..i-1] với i <= j (nếu có). (*)
Như vậy ta chỉ cần ghi nhận sự khác nhau giữa số lượng 'A' và 'B' khi duyệt chuỗi lần lượt từ trái sang phải. Số lượng đoạn [i, j] cần tìm chính là số lần hiệu bị trùng lặp.

Nhìn lại đoạn code, tại mỗi bước i,
Mã:
sum    = hiệu của số lượng chữ số 'B' và số lượng chữ số 'A' từ 1 tới i.

c[sum] = số lần xuất hiện của hiệu 'sum' này. Ví dụ, nếu giá trị của c[sum] là 1, thì hiệu này đã xuất hiện 1 lần.
Nếu như gặp 'sum' một lần nữa thì ta chắc chắn có được một đoạn [i, j] cần tìm theo (*).

count  = số đoạn [i, j] thỏa mãn yêu cầu đề bài (số lần đẳng thức (*) được thỏa mãn).

I hope it helps.
 
Sửa lần cuối:
bạn có thể giải thích giải thuật trên cho mình thông qua ví dụ trên được không ak
Vd ABAB -> 4
 

tengiday

Happy life
Nếu s = "ABAB", thì:
i = 0 (ban đầu)
Mã:
sum = 0     count = 0     c[0] = 1 // lần đầu tiên 'sum' bằng 0.
i = 1, s[1..1] = 'A'
Mã:
sum = -1     count = 0     c[-1] = 1 // lần đầu tiên 'sum' bằng -1.
i = 2, s[1..2] = 'AB'
Mã:
sum = 0    count = 1     c[0] = 2 // lần thứ hai 'sum' bằng 0.
i = 3, s[1..3] = 'ABA'
Mã:
sum = -1     count = 2     c[-1] = 2 // lần thứ hai 'sum' bằng -1.
i = 4, s[1..4] = 'ABAB'
Mã:
sum = 0     count = 4     c[0] = 3 // lần thứ ba 'sum' bằng 0.
Bạn nên hiểu phần giải nghĩa của mình ở phía trên cho rõ thì sẽ dễ hơn. Cái (*) mình ghi chính là ý tưởng chính của cách làm.
 
mình thấy ở đây ta ghi nhận số lần xuất hiện của 'A' và 'B' . mình thắc mắc không biết vì sao ta chưa duyệt mà ghi nhận đã được 1 chữ 'B'
 

tengiday

Happy life
Ý của bạn có phải là 'c[0] = 1' không? Cái đó ko phải là 1 chữ 'B', mà là chuỗi rỗng (chưa duyệt gì cả) nên số lượng 'A' bằng số lượng 'B' (tức là hiệu là 0). Bạn lưu ý ở đây tính hiệu của số lượng 'B' và 'A', biến 'sum' chính là tính cái này.
 

Thống kê

Chủ đề
100,752
Bài viết
467,583
Thành viên
339,851
Thành viên mới nhất
Đông Âu
Top