Rabin-Karp có thực sự cần tôi quan tâm đến việc áp dụng thao tác mod Q trên băm lăn không?


8

Tôi đã đọc về thuật toán Rabin Karp và tôi cứ tự hỏi không biết vấn đề lớn với việc giữ các giá trị băm lăn của chúng ta giới hạn bởi một giá trị Q là gì?

Tôi đã nghĩ rằng đại diện số nguyên của chúng tôi trên máy tính thông thường là 2 bổ sung, nó thực sự tương đương chính xác như ràng buộc tất cả các hoạt động của chúng tôi trong các băm lăn bằng 2 ^ 31, do đó, nói cách khác, tôi chỉ đơn giản là không quan tâm. Thêm vào đó, chúng ta càng bị ràng buộc hoặc băm nhỏ, chúng ta càng có nhiều va chạm, do đó, một Q lớn hơn sẽ bằng với hiệu suất được cải thiện!

Tôi đã thử mã hóa một triển khai (Java) đơn giản:

public static int rabinKarp(String text, String pattern) {
    if (text.length() < pattern.length()) {
        return -1;
    } else {
        int patternHash = 0;
        int textHash = 0;
        int pow = 1;

        // preprocessing the pattern and the first characters of the text string
        for (int i = pattern.length()-1; i >= 0; --i) {
            patternHash += pattern.charAt(i) * pow;
            textHash += text.charAt(i) * pow;
            pow *= 10;
        }
        pow /= 10;

        // actual search
        if (patternHash == textHash && areEqual(text, 0, pattern)) {
            return 0;
        } else {
            for (int i = 1; i < text.length()-pattern.length()+1; ++i) {
                textHash -= text.charAt(i-1)*pow;
                textHash *= 10;
                textHash += text.charAt(i+pattern.length()-1);
                if (textHash == patternHash && areEqual(text, i, pattern)) {
                    return i;
                }
            }
            return -1;
        }
    }
}

Từ một số thử nghiệm sơ bộ, giả thuyết của tôi dường như chính xác về mặt thực nghiệm, nhưng tôi chưa thấy nó được viết ở bất cứ đâu, vì vậy tôi không khỏi thắc mắc ..

Tui bỏ lỡ điều gì vậy?


2
Vấn đề lớn có lẽ là chúng tôi muốn thực hiện tất cả các tính toán modulo Q, có lẽ là một số nguyên tố lớn gần với MAXINT. Điều đó có lẽ sẽ dẫn đến một hàm băm tốt hơn. Tuy nhiên, thật khó để biết vì tôi không biết thuật toán tham chiếu của bạn là gì - có nhiều biến thể của Rabin kèm Karp. Tôi cũng không thích đọc mã Java. Chắc chắn bạn có thể tóm tắt thuật toán của bạn trong mã giả thay thế.
Yuval Filmus 16/07/2015

Câu trả lời:


10

Vâng, trong thực tế, bạn có thể có được bằng cách chỉ để cho các tính toán tràn. Bạn đang làm việc hiệu quả modulo232. Nó cũng có lợi thế là không yêu cầu tính toán modulo (đắt tiền). Tuy nhiên, nó thiếu một số đảm bảo hiệu suất lý thuyết. Bạn cần phải rất cẩn thận với sự lựa chọn của cơ sở (trong trường hợp này:10) đối với mô đun.

Đặc biệt, sự lựa chọn của bạn về 10rất là nghèo. Lưu ý rằng1032=232532, vì thế 1032 mod 232=0. Điều này có nghĩa là chỉ cuối cùng32 các ký tự của chuỗi được đưa vào tài khoản trong hàm băm, do đó người ta có thể xây dựng một đầu vào mà thuật toán của bạn thực hiện rất kém.

Hãy để haystack là một chuỗi m 1nghĩa là 1111111 và kim một chuỗi bao gồm n 1của, một 0, và sau đó 32 1'S. Bởi vì chuỗi kết thúc bằng32 1Mọi vị trí sẽ dẫn đến một cú đánh giả, và thuật toán sẽ cần lặp lại n 1Trước khi gặp số 0, nghĩa là bạn sẽ nhận được Ω(nm) thời gian chạy

Tôi đã thử nghiệm thuật toán của bạn trên một đầu vào trong đó n=3000,m=n2=9106. Nó đã18 giây để chạy trên đầu vào kết thúc bằng 32 1, nhưng chỉ 200ms cho một chuỗi kết thúc bằng 31 1'S.

Vấn đề là ở đó 10không tương đối nguyên tố với mô đun. Ví dụ, lấy9 vì cơ sở làm cho chương trình của bạn hoạt động tốt hơn nhiều, chỉ lấy 200ms cho trường hợp với 32 1'S. Tất nhiên, lấy một mô đun nguyên tố sẽ giải quyết được một phần vấn đề này vì cơ sở sẽ tự động tương đối nguyên tố với nó. Tuy nhiên, đây không phải là lý do duy nhất để thích một mô đun nguyên tố.

Bây giờ, ngay cả khi mô-đun n và cơ sở blà tương đối chính, những điều không mong muốn vẫn có thể xảy ra. Ví dụ, có mộtkbk=1 mod n. Đó là điều không mong muốn chok là nhỏ, vì hàm băm không thể phân biệt mọi ith nhân vật từ mọi i+kthtính cách. Trong thuật ngữ toán học, bạn muốn thứ tự củab mod n càng lớn càng tốt.

Lệnh của b mod n luôn luôn có nhiều nhất là hàm Euler-Phi ϕ(n). Cho một nguyên tốp, ϕ(p)=p1 trong khi đối với các số nguyên tố nnó sẽ nhỏ hơn Vì vậy, lấyn trở thành một nguyên tố sẽ cho phép nhiều giá trị của bklà "hữu ích". Tốt nhất, người ta nên dùngb là một modulo gốc nguyên thủy n, làm điều đó bk=1 mod n không giữ bất kỳ giá trị nào của 0<k<ϕ(n).

Lưu ý rằng bạn luôn có thể xây dựng các trường hợp mà hiệu suất kém và để bảo vệ chống lại "các cuộc tấn công" khỏi một đối thủ, bạn cần lấy cơ sở và mô đun làm giá trị ngẫu nhiên.


Một câu trả lời tuyệt vời. Tôi muốn thêm điều đó, choQ=2k, có chuỗi Thue-Morse : cho tùy ýp, nó có các chuỗi ngắn không thể phân biệt bằng cách băm đa thức. Ví dụ vớiQ=264, các chuỗi con kết thúc trên bội số của 4096=212 tất cả sẽ có băm không, bất kể p. Đây là một lời giải thích phổ biến.
Gass
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.