Hướng dẫn giải của Mofk Cup Round 2 - SUFFIX ARRAY


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Đầu tiên, nếu ~p~ là dãy giảm thì đáp án là ~n + 1~, các xâu thỏa mãn lần lượt là "000...0", "100...0", "110...0", "111...0", ..., "111...1". Đây là trường hợp mà ~Mofk~ khóc thét vì quá nhiều xâu ~s~ tồn tại.

Nếu ~p~ không là dãy giảm, gọi ~L~ là độ dài dài nhất của đoạn tiền tố thỏa mãn ~p[i] = n - i + 1~ với mọi ~i~. Lúc này ~s[p[i]] = 0~ với mọi ~i \leq L~, vì nếu ~s[p[i]]~ = 1 với giá trị ~i \leq L~ nào đó, thì tất cả giá trị ~s[p[i + 1]], s[p[i + 2]],..., s[p[n]]~ đều phải bằng ~1~, nghĩa là ~s~ có dạng "111...11000...0", mà dãy hậu tố của dạng này phải là dãy giảm, mâu thuẫn với điều kiện ~p~ không là dãy giảm.

Vậy sau khi tìm ~L~ và xử lý được đoạn tiền tố của ~p~, ta còn lại đoạn ~p[L + 1..n]~ hợp với ~s[1..n - L]~. Gọi ~j~ là vị trí của ~n - L~ trong ~p~ (~p[j] = n - L~, lưu ý rằng ~j > L + 1~ theo định nghĩa của ~L~ bên trên). Lúc này ta có ~s[p[j]] = 1~, bởi nếu ~s[p[j]] = 0~ thì ~j~ phải bằng ~L + 1~ (vì đoạn s[n - L..n] khi đó sẽ toàn giá trị ~0~).

Khi ~s[p[j]] = 1~, nghĩa là s[n - L..n] = "1000...0", là xâu nhỏ nhất bắt đầu bằng ~1~, vậy nên các xâu hậu tố khác muốn nhỏ hơn ~s[n-L..n]~ thì chỉ có thể bắt đầu bằng ~0~, nghĩa là ~s[p[k]] = 0~ với mọi ~k < j~. Cuối cùng, theo định nghĩa của dãy hậu tố, ta có ~s[p[k]] = 1~ với mọi ~k > j~.

Nói tóm gọn, từ các giá trị ~L, j~, ta xác định được xâu ~s~ duy nhất có khả năng nhận ~p~ làm dãy hậu tố. Ta chỉ cần kiểm tra xem xâu ~s~ có thực sự nhận ~p~ là hậu tố hay không. Nếu có, đáp án là ~1~ và ~Mofk~ sẽ rất vui mừng vì đền được binh khí cho thầy, nếu không, đáp án là ~0~ và ~Mofk~ sẽ rơi vào trạng thái hoang mang tột độ vì không những làm hỏng binh khí mà còn tìm sai luôn cái dãy ~p~.


Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.