public class RabinKarp { private String pat; //模式字符串 private long patHash; //模式字符串散列值 private int M; //模式字符串的长度 private long Q; //很大的素数 private int R; //字母表的大小 private long RM; //R^(M-1) % Q
public RabinKarp(char[] pat, int R){ this.pat = String.valueOf(pat); this.R = R; } public RabinKarp(String pat){ this.pat = pat; R = 256; M = pat.length(); Q = longRandomPrime(); RM = 1; for(int i=1; i<=M-1; i++){ RM = (R * RM) % Q; } patHash = hash(pat, M); } private long hash(String str, int M){ long h = 0; for(int i=0; i < M; i++){ h = (R * h + str.charAt(i)) % Q; } return h; } public boolean check(String txt,int i){ for(int j = 0; j < M; j++){ if(pat.charAt(j) != txt.charAt(i+j)) return false; } return true; } private static long longRandomPrime() { BigInteger prime = BigInteger.probablePrime(31, new Random()); return prime.longValue(); } private int search(String txt){ int N = txt.length(); if(N < M) return N; long txtHash = hash(txt,M); if((txtHash == patHash) && check(txt, 0)) return 0; for(int i = M; i < N; i++){ txtHash = (txtHash + Q - RM*txt.charAt(i-M) % Q) % Q; txtHash = (txtHash*R + txt.charAt(i)) % Q; int offset = i-M+1; if((patHash == txtHash) && check(txt, offset)) return offset; } return N; } public static void main(String[] args) { String pat = args[0]; String txt = args[1];
RabinKarp searcher = new RabinKarp(pat); int offset = searcher.search(txt); // print results StdOut.println("text: " + txt);
// from brute force search method 1 StdOut.print("pattern: "); for (int i = 0; i < offset; i++) StdOut.print(" "); StdOut.println(pat); } }