Đây là một trong những dự án nghiên cứu mà tôi đang thực hiện. Yêu cầu gần như chính xác là của bạn và chúng tôi đã phát triển các thuật toán tốt để giải quyết vấn đề.
Đầu vào
Đầu vào là một dòng vô tận các từ hoặc cụm từ tiếng Anh (chúng tôi gọi chúng là tokens
).
Đầu ra
- Xuất ra N mã thông báo hàng đầu mà chúng tôi đã thấy cho đến nay (từ tất cả các mã thông báo mà chúng tôi đã thấy!)
- Xuất ra N mã thông báo hàng đầu trong một cửa sổ lịch sử, chẳng hạn như ngày trước hoặc tuần trước.
Một ứng dụng của nghiên cứu này là tìm chủ đề nóng hoặc xu hướng của chủ đề trên Twitter hoặc Facebook. Chúng tôi có một trình thu thập thông tin thu thập dữ liệu trên trang web, tạo ra một luồng từ, sẽ đưa vào hệ thống. Sau đó, hệ thống sẽ xuất ra các từ hoặc cụm từ có tần suất cao nhất về tổng thể hoặc lịch sử. Hãy tưởng tượng trong vài tuần trước, cụm từ "World Cup" sẽ xuất hiện nhiều lần trên Twitter. “Bạch tuộc Paul” cũng vậy. :)
Chuỗi thành số nguyên
Hệ thống có một số nguyên ID cho mỗi từ. Mặc dù có thể có gần như vô hạn các từ trên Internet, nhưng sau khi tích lũy một lượng lớn các từ, khả năng tìm thấy từ mới ngày càng thấp. Chúng tôi đã tìm thấy 4 triệu từ khác nhau và chỉ định một ID duy nhất cho mỗi từ. Toàn bộ tập dữ liệu này có thể được tải vào bộ nhớ dưới dạng bảng băm, tiêu tốn khoảng 300MB bộ nhớ. (Chúng tôi đã triển khai bảng băm của riêng mình. Việc triển khai Java chiếm bộ nhớ lớn)
Sau đó, mỗi cụm từ có thể được xác định là một mảng các số nguyên.
Điều này rất quan trọng, bởi vì sắp xếp và so sánh trên số nguyên nhanh hơn nhiều so với trên chuỗi.
Lưu trữ dữ liệu
Hệ thống giữ dữ liệu lưu trữ cho mọi mã thông báo. Về cơ bản đó là các cặp (Token, Frequency)
. Tuy nhiên, bảng lưu trữ dữ liệu sẽ rất lớn nên chúng ta phải phân vùng bảng về mặt vật lý. Một khi lược đồ phân vùng dựa trên ngrams của mã thông báo. Nếu mã thông báo là một từ đơn lẻ, nó là 1gram. Nếu mã thông báo là cụm từ gồm hai từ, nó là 2gram. Và điều này tiếp tục. Khoảng 4gram, chúng tôi có 1 tỷ bản ghi, với kích thước bảng khoảng 60GB.
Xử lý luồng đến
Hệ thống sẽ hấp thụ các câu đến cho đến khi bộ nhớ được sử dụng hết (Ya, chúng ta cần một MemoryManager). Sau khi lấy N câu và lưu vào bộ nhớ, hệ thống tạm dừng và bắt đầu mã hóa từng câu thành các từ và cụm từ. Mỗi mã thông báo (từ hoặc cụm từ) được đếm.
Đối với các mã thông báo có tần suất cao, chúng luôn được lưu giữ trong bộ nhớ. Đối với các mã thông báo ít thường xuyên hơn, chúng được sắp xếp dựa trên ID (hãy nhớ rằng chúng tôi dịch Chuỗi thành một mảng số nguyên) và được tuần tự hóa thành tệp đĩa.
(Tuy nhiên, đối với vấn đề của bạn, vì bạn chỉ đếm các từ, nên bạn chỉ có thể đặt tất cả bản đồ tần suất từ vào bộ nhớ. Một cấu trúc dữ liệu được thiết kế cẩn thận sẽ chỉ tiêu tốn bộ nhớ 300MB cho 4 triệu từ khác nhau. Một số gợi ý: sử dụng ký tự ASCII để đại diện cho Strings), và điều này có thể chấp nhận được.
Trong khi đó, sẽ có một quá trình khác được kích hoạt khi nó tìm thấy bất kỳ tệp đĩa nào do hệ thống tạo ra, sau đó bắt đầu hợp nhất nó. Vì tệp đĩa được sắp xếp nên việc hợp nhất sẽ diễn ra một quá trình tương tự như sắp xếp hợp nhất. Một số thiết kế cũng cần được quan tâm tại đây, vì chúng tôi muốn tránh quá nhiều lần tìm kiếm đĩa ngẫu nhiên. Ý tưởng là tránh đọc (quá trình hợp nhất) / ghi (đầu ra của hệ thống) cùng một lúc và để quá trình hợp nhất đọc tạo thành một đĩa trong khi ghi vào một đĩa khác. Điều này tương tự như thực hiện một khóa.
Cuối ngày
Vào cuối ngày, hệ thống sẽ có nhiều mã thông báo thường xuyên với tần suất được lưu trữ trong bộ nhớ và nhiều mã thông báo khác ít thường xuyên hơn được lưu trữ trong một số tệp đĩa (và mỗi tệp được sắp xếp).
Hệ thống chuyển bản đồ trong bộ nhớ vào một tệp đĩa (sắp xếp nó). Bây giờ, vấn đề trở thành hợp nhất một tập hợp các tệp đĩa đã được sắp xếp. Sử dụng quy trình tương tự, chúng tôi sẽ nhận được một tệp đĩa được sắp xếp ở cuối.
Sau đó, nhiệm vụ cuối cùng là hợp nhất tệp đĩa đã được sắp xếp vào cơ sở dữ liệu lưu trữ. Tùy thuộc vào kích thước của cơ sở dữ liệu lưu trữ, thuật toán hoạt động như dưới đây nếu nó đủ lớn:
for each record in sorted disk file
update archive database by increasing frequency
if rowcount == 0 then put the record into a list
end for
for each record in the list of having rowcount == 0
insert into archive database
end for
Linh tính là sau một thời gian, số lần chèn sẽ ngày càng ít hơn. Ngày càng có nhiều hoạt động sẽ chỉ được cập nhật. Và việc cập nhật này sẽ không bị phạt theo chỉ số.
Hy vọng toàn bộ lời giải thích này sẽ hữu ích. :)
what is the most frequent item in the subsequence [2; 2; 3; 3; 3; 4; 4; 4; 4; 5; 5] of your sequence?