Rabin Karp算法

  1. pub fn rabin_karp(target: String, pattern: String) -> Vec<usize> {
  2. // Quick exit
  3. if target.is_empty() || pattern.is_empty() || pattern.len() > target.len() {
  4. return vec![];
  5. }
  6. let string: String = (&pattern[0..pattern.len()]).to_string();
  7. let hash_pattern = hash(string.clone());
  8. let mut ret = vec![];
  9. for i in 0..(target.len() - pattern.len() + 1) {
  10. let s = (&target[i..(i + pattern.len())]).to_string();
  11. let string_hash = hash(s.clone());
  12. if string_hash == hash_pattern && s == string {
  13. ret.push(i);
  14. }
  15. }
  16. ret
  17. }
  18. fn hash(mut s: String) -> u16 {
  19. let prime: u16 = 101;
  20. let last_char = s
  21. .drain(s.len() - 1..)
  22. .next()
  23. .expect("Failed to get the last char of the string");
  24. let mut res: u16 = 0;
  25. for (i, &c) in s.as_bytes().iter().enumerate() {
  26. if i == 0 {
  27. res = (c as u16 * 256) % prime;
  28. } else {
  29. res = (((res + c as u16) % 101) * 256) % 101;
  30. }
  31. }
  32. (res + last_char as u16) % prime
  33. }
  34. #[cfg(test)]
  35. mod tests {
  36. use super::*;
  37. #[test]
  38. fn hi_hash() {
  39. let hash_result = hash("hi".to_string());
  40. assert_eq!(hash_result, 65);
  41. }
  42. #[test]
  43. fn abr_hash() {
  44. let hash_result = hash("abr".to_string());
  45. assert_eq!(hash_result, 4);
  46. }
  47. #[test]
  48. fn bra_hash() {
  49. let hash_result = hash("bra".to_string());
  50. assert_eq!(hash_result, 30);
  51. }
  52. // Attribution to @pgimalac for his tests from Knuth-Morris-Pratt
  53. #[test]
  54. fn each_letter_matches() {
  55. let index = rabin_karp("aaa".to_string(), "a".to_string());
  56. assert_eq!(index, vec![0, 1, 2]);
  57. }
  58. #[test]
  59. fn a_few_separate_matches() {
  60. let index = rabin_karp("abababa".to_string(), "ab".to_string());
  61. assert_eq!(index, vec![0, 2, 4]);
  62. }
  63. #[test]
  64. fn one_match() {
  65. let index = rabin_karp("ABC ABCDAB ABCDABCDABDE".to_string(), "ABCDABD".to_string());
  66. assert_eq!(index, vec![15]);
  67. }
  68. #[test]
  69. fn lots_of_matches() {
  70. let index = rabin_karp("aaabaabaaaaa".to_string(), "aa".to_string());
  71. assert_eq!(index, vec![0, 1, 4, 7, 8, 9, 10]);
  72. }
  73. #[test]
  74. fn lots_of_intricate_matches() {
  75. let index = rabin_karp("ababababa".to_string(), "aba".to_string());
  76. assert_eq!(index, vec![0, 2, 4, 6]);
  77. }
  78. #[test]
  79. fn not_found0() {
  80. let index = rabin_karp("abcde".to_string(), "f".to_string());
  81. assert_eq!(index, vec![]);
  82. }
  83. #[test]
  84. fn not_found1() {
  85. let index = rabin_karp("abcde".to_string(), "ac".to_string());
  86. assert_eq!(index, vec![]);
  87. }
  88. #[test]
  89. fn not_found2() {
  90. let index = rabin_karp("ababab".to_string(), "bababa".to_string());
  91. assert_eq!(index, vec![]);
  92. }
  93. #[test]
  94. fn empty_string() {
  95. let index = rabin_karp("".to_string(), "abcdef".to_string());
  96. assert_eq!(index, vec![]);
  97. }
  98. }