Tôi có thể đảm bảo với bạn, chức năng strcmp
là TUYỆT ĐỐI KHÔNG phải là nút cổ chai. Thông thường, strcmp được tối ưu hóa tốt và có thể so sánh 32 hoặc 64 bit đối với các chuỗi dài hơn 4/8 byte tùy thuộc vào kiến trúc. Cả newlib và GNU libc đều làm điều này. Nhưng ngay cả khi bạn đã xem xét từng byte trong cả hai chuỗi 20 lần, nó không quan trọng nhiều như algo & các lựa chọn cấu trúc dữ liệu được tạo ở đây.
Cổ chai thực sự là thuật toán tìm kiếm O (N). Một pass O (N log N) duy nhất tại file có thể được sử dụng ở cấu trúc dữ liệu thích hợp (cho dù đó là BST bình thường, một trie hay chỉ là một mảng được sắp xếp đơn giản) để thực hiện tra cứu O (log N).
Hãy theo tôi ở đây - rất nhiều bài toán sau. Nhưng tôi nghĩ đây là cơ hội tốt để minh họa tại sao lựa chọn thuật toán & cấu trúc dữ liệu đôi khi FAR quan trọng hơn so với phương pháp so sánh chuỗi. Steve chạm vào điều này, nhưng tôi muốn giải thích nó sâu hơn một chút.
Với N = 1e6, nhật ký (1e6, 2) = 19.9, do đó, làm tròn tối đa 20 so sánh trên cấu trúc dữ liệu lý tưởng.
Hiện tại bạn đang thực hiện tìm kiếm trường hợp xấu nhất của các hoạt động O (N) hoặc 1e6.
Vì vậy, giả sử bạn chỉ xây dựng một cây đỏ đen với thời gian chèn O (log N) và bạn chèn N mục, đó là thời gian O (N log N) để tạo cây. Vì vậy, đó là hoạt động 1e6 x 20 hoặc 20e6 cần thiết để xây dựng cây của bạn.
Trong phương pháp hiện tại của bạn, xây dựng cấu trúc dữ liệu là hoạt động O (N) hoặc 1e6, nhưng thời gian tìm kiếm trường hợp xấu nhất của bạn là O (N). Vì vậy, vào thời điểm bạn đọc các tập tin và làm chỉ 20 hoạt động tìm kiếm, bạn đang lên đến một trường hợp lý thuyết tồi tệ nhất của 21.000.000 hoạt động. Bằng cách so sánh, trường hợp xấu nhất của bạn với một cây đỏ đen và 20 tìm kiếm là 20.000.400 hoạt động, hoặc 999.600 hoạt động TỐT hơn so với tìm kiếm O (N) trên một mảng chưa được sắp xếp. Vì vậy, tại 20 tìm kiếm, bạn đang ở điểm đầu tiên mà một cấu trúc dữ liệu phức tạp hơn thực sự trả hết. Nhưng hãy xem điều gì xảy ra ở 1000 tìm kiếm:
Mảng không phân loại = khởi tạo + 1000 x thời gian tìm kiếm = O (N) + 1000 * O (N) = 1.000.000 + 2.000.000.000 = 2,001.000.000 hoạt động.
Đỏ đen = khởi tạo + 1000 x thời gian tìm kiếm = O (N log N) + 1000 * O (nhật ký N) = 20.000.000 + 20.000 = 20,020.000 hoạt động.
2,001.000.000/20,020,000 ~ = 100x như nhiều thao tác cho tìm kiếm O (N).
Tại 1e6 tìm kiếm, đó là (1e6 + 1e6 * 1e6)/(20e6 + 1e6 * 20) = 25.000x là nhiều thao tác.
Giả sử máy tính của bạn có thể xử lý hoạt động 40e6 'cần thiết để thực hiện tìm kiếm nhật ký N trong 1 phút. Sẽ mất 25.000 phút hoặc 17 NGÀY để thực hiện cùng một công việc với thuật toán hiện tại của bạn. Hoặc một cách khác để xem xét là thuật toán tìm kiếm O (N) chỉ có thể xử lý 39 tìm kiếm trong thời gian thuật toán O (log N) có thể thực hiện 1.000.000. Và càng có nhiều tìm kiếm bạn thực hiện thì càng tệ hơn.
Xem câu trả lời từ Steve và dirkgently cho một số lựa chọn tốt hơn về cấu trúc dữ liệu & thuật toán. Thận trọng duy nhất của tôi là qsort()
được đề xuất bởi Steve có thể có độ phức tạp xấu nhất của O (N * N), xa hơn rất nhiều so với O (N log N) mà bạn nhận được với heapsort hoặc cấu trúc giống cây.
Nếu bạn có thể sắp xếp các dòng, chắc chắn. – dbrank0
Nếu bạn có thể băm, băm. – wildplasser
@KingsIndian: không, bởi vì câu hỏi thực sự ở đây không phải là "làm thế nào để so sánh hai chuỗi", đó là "làm thế nào để kiểm tra một chuỗi để ngăn chặn trong một bộ sưu tập lớn các chuỗi". –