Z-function là gì?
Z-function là một kỹ thuật trong xử lý chuỗi (string processing), thường dùng trong các bài toán liên quan đến việc tìm kiếm mẫu con (pattern matching).
Cho một chuỗi S có độ dài n, Z-function là một mảng Z[] cũng có độ dài n, trong đó:
Z[i]là độ dài phần tiền tố dài nhất bắt đầu từ vị tríivà cũng là tiền tố của chuỗiS.
Hay nói cách khác:Z[i] = length of the longest substring starting at i which is also a prefix of S.
Ví dụ minh họa
Với chuỗi S = "aabcaabxaaaz", mảng Z-function sẽ là:
Index: 0 1 2 3 4 5 6 7 8 9 10 11 S: a a b c a a b x a a a z Z-function: 0 1 0 0 3 1 0 0 2 1 1 0
Giải thích:
Z[1] = 1vì chuỗi bắt đầu từS[1] = "a"khớp với tiền tố"a"củaS.Z[4] = 3vì"aab"(bắt đầu từS[4]) khớp với tiền tố"aab".
Ứng dụng của Z-function trong lập trình
a. Tìm tất cả vị trí khớp của một mẫu P trong chuỗi T:
Giải pháp:
- Tạo chuỗi
S = P + "#" + T(ký tự#là phân cách không xuất hiện trong cảPvàT). - Tính Z-function của
S. - Mỗi
imàZ[i] == |P|là vị trí khớp của mẫuPtrongT.
Ví dụ:
Tìm mẫu abc trong văn bản abcabcabc.
string P = "abc", T = "abcabcabc";
string S = P + "#" + T;
vector<int> Z = computeZ(S);
for (int i = P.size() + 1; i < S.size(); ++i) {
if (Z[i] == P.size()) {
cout << "Match at position " << i - P.size() - 1 << endl;
}
}
b. Lập trình thi đấu – bài toán lặp tiền tố
Z-function thường dùng trong:
- Kiểm tra xem chuỗi có cấu trúc lặp không (ví dụ, chuỗi
abababcó thể viết lại thànhablặp 3 lần). - Tính toán số lần một mẫu xuất hiện như tiền tố trong nhiều vị trí.
- Các bài toán về border (tiền tố cũng là hậu tố).
Ưu điểm
- Tính Z-function có thể thực hiện trong thời gian O(n).
- Có thể dùng thay thế cho thuật toán KMP phức tạp mà vẫn làm được các bài toán matching hiệu quả.
Tổng kết
Z-function là một kỹ thuật mạnh mẽ và dễ cài đặt trong xử lý chuỗi. Nó đặc biệt hữu ích trong lập trình thi đấu và các bài toán pattern matching, kiểm tra tính lặp, hoặc tiền tố đặc biệt. Nắm vững Z-function giúp bạn xử lý hiệu quả nhiều bài toán chuỗi tưởng như rất phức tạp.
