Nếu chúng tôi có N
từ, mỗi từ có độ dài tối đa L
, thuật toán của bạn sẽ mất O(N*L^3)
(giả sử thêm vào trie là tuyến tính có chiều dài thêm từ). Tuy nhiên, kích thước của số lượng trie (số lượng nút) tối đa là O(N*L^2)
, vì vậy có vẻ như bạn đang lãng phí thời gian và bạn có thể làm tốt hơn.
Và thực sự bạn có thể, nhưng bạn phải kéo một vài thủ thuật từ tay áo. Ngoài ra, bạn sẽ không còn cần trie.
.substring()
trong thời gian liên tục
Trong Java 7, mỗi String
đã có một mảng ủng hộ char[]
cũng như vị trí bắt đầu và thời gian. Điều này cho phép phương thức .substring()
chạy trong thời gian không đổi, vì String
là lớp không thay đổi. Đối tượng String
mới với cùng sự ủng hộ char[]
mảng đã được tạo, chỉ với vị trí bắt đầu và độ dài khác nhau.
Bạn sẽ cần phải mở rộng này một chút, để hỗ trợ thêm ở cuối chuỗi, bằng cách tăng độ dài. Luôn tạo một đối tượng chuỗi mới, nhưng để lại mảng sao lưu giống nhau.
- Tính toán lại băm trong thời gian liên tục sau khi gắn thêm ký tự đơn
Một lần nữa, hãy để tôi sử dụng hashCode()
chức năng của Java cho String
:
int hash = 0;
for (int i = 0; i < data.length; i++) {
hash = 31 * hash + data[i];
} // data is the backing array
Bây giờ, làm thế nào sẽ thay đổi băm sau khi thêm một ký tự đơn ở cuối từ? Dễ dàng, chỉ cần thêm giá trị của nó (mã ASCII) nhân với 31^length
. Bạn có thể giữ quyền hạn của 31 trong một số bảng riêng biệt, các số nguyên tố khác có thể được sử dụng là tốt.
- Lưu trữ tất cả các chuỗi con trong đơn
HashMap
Với việc sử dụng thủ đoạn 1 và 2, bạn có thể tạo ra tất cả các chuỗi con trong thời gian O(N*L^2)
, mà là tổng số của chuỗi con. Chỉ cần luôn bắt đầu bằng chuỗi có độ dài một và thêm một ký tự cùng một lúc. Đặt tất cả các chuỗi của bạn vào một HashMap duy nhất, để giảm các bản sao.
(Bạn có thể bỏ 2 và 3 và loại bỏ duplicities khi/sau khi phân loại, có lẽ nó sẽ còn nhanh hơn.)
- Sắp xếp chuỗi con của bạn và bạn tốt để đi.
Vâng, khi tôi đã đến điểm 4, tôi nhận ra kế hoạch của tôi sẽ không làm việc, vì trong phân loại bạn cần phải so sánh chuỗi, và có thể mất thời gian O(L)
. Tôi đã đưa ra nhiều nỗ lực để giải quyết nó, trong đó có xô phân loại, nhưng không ai sẽ là nhanh hơn so với ban đầu O(N*L^3)
tôi sẽ chỉ trả lời ở đây trong trường hợp nó truyền cảm hứng cho một ai đó.
Trong trường hợp bạn không biết Aho-Corasic algorithm, hãy nhìn vào đó, nó có thể có một số sử dụng cho vấn đề của bạn.
Tôi không bị coi thường nhưng xem xét xử lý của bạn, câu trả lời này khá là mỉa mai. :) – Bhoot
@Bhoot: Haha! Không có sự xúc phạm nào. – n00bc0d3r
Tôi khuyên bạn nên triển khai tập hợp các phần tử được thêm vào dưới dạng một số loại 'HashSet', vì bạn có thể tính lại hàm băm cho chuỗi khi thêm hoặc xóa một chữ cái trong thời gian không đổi. – kajacx