📜  在Java使用滚动哈希实现Rabin Karp算法

📅  最后修改于: 2021-04-17 17:51:23             🧑  作者: Mango

字符串有很多模式搜索算法。 KMP算法,Z算法Rabin Karp算法等是朴素模式搜索算法的优化。

朴素模式搜索算法:

Input   :  "AABACACAACAC"
Pattern :  "CAC"
Output  :  [4,9]

AABACACAACAC

执行:

Java
// Java Program to Search for a Pattern String in the Input
// String returning the indicies
  
// Importing input java classes
import java.io.*;
  
// Main class
public class GFG {
  
    // Method 1
    // To find pattern in the string
    static void search(String s, String pattern)
    {
        // Iterating over the string in which to be searched
        // for using the length() method
        for (int i = 0; i <= s.length() - pattern.length();
             ++i) {
  
            int check = 1;
  
            // Iterating over the string for which is to be
            // searched using the length() method
            for (int j = 0; j < pattern.length(); ++j) {
  
                // Now, checking the elements of pattern
                // with the given string using theb charAt()
                // method
                if (s.charAt(i + j) != pattern.charAt(j)) {
  
                    // Setting check to zero as pattern is
                    // not detected here
                    check = 0;
  
                    // Break statement to hault 
                    // execution of code
                    break;
                }
            }
  
            // Now if the check remains same as declared
            // then pattern is detedcted at least once
            if (check == 1) {
  
                // Printing the position(index) of the
                // pattern string in the input string
                System.out.print(i + " , ");
            }
        }
    }
  
    // Metohd 2
    // Main driver method
    public static void main(String[] args)
    {
        // Given custom input string
        String s = "AABACACAACAC";
  
        // Pattern to be looked after in
        // the above input string
        String pattern = "CAC";
  
        // Display message for interpreting the indicies
        // ai where if the pattern exists
        System.out.print(
            "Pattern is found at the indicies : ");
  
        // Calling the above search() method
        // in the main() method
        search(s, pattern);
    }
}


Java
// Java Program to illsutating Simple Rolling Hashing
  
// Importing input output classes
import java.io.*;
  
// Main class
class GFG {
  
    // Method 1
    // To search the pattern
    static void search(String S, String pattern)
    {
        // Declaring and initializing the hash values
        int hash1 = 0;
        int hash2 = 0;
  
        // Iterating over the pattern string to be matched
        // over
        for (int i = 0; i < pattern.length(); ++i) {
  
            // Storting the hash value of the pattern
            hash1 += pattern.charAt(i) - 'A';
  
            // Storing First hash value of the string
            hash2 += S.charAt(i) - 'A';
        }
  
        // Initially declaring with zero
        int j = 0;
  
        // Iterating over the pattern string to vheckout
        // hash values
        for (int i = 0; i < S.length() - pattern.length();
             ++i) {
  
            // Checking the hash value
            if (hash2 == hash1) {
  
                // Checking the value
                for (j = 0; j < pattern.length(); ++j) {
  
                    // Checking for detectio of pattern in a
                    // pattern
                    if (pattern.charAt(j)
                        != S.charAt(i + j)) {
  
                        // Break statement to hault the
                        // execution of program as no
                        // pattern found
                        break;
                    }
                }
            }
  
            // If execution is not stopped means
            // pattern(sub-string) is present
  
            // So now simply detecting for one or more
            // ocurences inbetween pattern string using the
            // length() method
            if (j == pattern.length()) {
  
                // Pattern is detected so printing the index
                System.out.println(i);
            }
  
            // Roll the hash value over the string detected
            hash2 = (int)((hash2) - (S.charAt(i) - 'A'))
                    + S.charAt(i + pattern.length()) - 'A';
        }
    }
  
    // Method 2
    // Main driver method
    public static void main(String[] args)
    { 
        
        // Input string to be traversed
        String S = "CACCACA";
  
        // Pattern string to be checked
        String pattern = "CAC";
  
        // Calliing the above search() method(Method1)
        // in the main() method
        search(S, pattern);
    }
}


输出
Pattern is found at the indicies : 4 , 9 , 

输出说明:

我们如何降低该算法的复杂性?

借助滚动哈希是可能的 Rabin Karp算法是朴素算法的优化算法之一,它通过在字符串滚动并搜索模式来执行搜索。

插图:

Input:  txt[] = "THIS IS A TEST TEXT"
        pat[] = "TEST"
Output: Pattern found at index 10

Input:  txt[] =  "AABAACAADAABAABA"
        pat[] =  "AABA"
Output: Pattern found at index 0
        Pattern found at index 9
        Pattern found at index 12

程序:

  • 计算模式的哈希值(通过创建自己的哈希函数或公式来确定每个字符的哈希值)
  • 遍历字符串检查匹配模式的大小所生成的每个子字符串的哈希值(如果匹配的话),并检查模式的每个字符,如果所有匹配的字符都打印字符串的起始索引。
  • 如果没有跳过第一个字符,添加下一个字符,我们不计算字符串中的下串的散列值的散列值相匹配转移到下一个字符只有我们滑动窗口跳过第一个字符,并添加通过计算其哈希值(即滚动哈希)来确定窗口中的最后一个字符。

执行:

假设长度为2的模式的简单滚动算法

  1. 初始化temp = 4(1 + 3)
  2. 将哈希值滚动到下一个元素。
  3. 循环’i'<= Array.length-pattern.length
  4. 从temp变量中删除第一个元素,然后在temp变量中添加下一个元素。 temp = temp-Array [i] + Array [i.pattern.length()]

Java

// Java Program to illsutating Simple Rolling Hashing
  
// Importing input output classes
import java.io.*;
  
// Main class
class GFG {
  
    // Method 1
    // To search the pattern
    static void search(String S, String pattern)
    {
        // Declaring and initializing the hash values
        int hash1 = 0;
        int hash2 = 0;
  
        // Iterating over the pattern string to be matched
        // over
        for (int i = 0; i < pattern.length(); ++i) {
  
            // Storting the hash value of the pattern
            hash1 += pattern.charAt(i) - 'A';
  
            // Storing First hash value of the string
            hash2 += S.charAt(i) - 'A';
        }
  
        // Initially declaring with zero
        int j = 0;
  
        // Iterating over the pattern string to vheckout
        // hash values
        for (int i = 0; i < S.length() - pattern.length();
             ++i) {
  
            // Checking the hash value
            if (hash2 == hash1) {
  
                // Checking the value
                for (j = 0; j < pattern.length(); ++j) {
  
                    // Checking for detectio of pattern in a
                    // pattern
                    if (pattern.charAt(j)
                        != S.charAt(i + j)) {
  
                        // Break statement to hault the
                        // execution of program as no
                        // pattern found
                        break;
                    }
                }
            }
  
            // If execution is not stopped means
            // pattern(sub-string) is present
  
            // So now simply detecting for one or more
            // ocurences inbetween pattern string using the
            // length() method
            if (j == pattern.length()) {
  
                // Pattern is detected so printing the index
                System.out.println(i);
            }
  
            // Roll the hash value over the string detected
            hash2 = (int)((hash2) - (S.charAt(i) - 'A'))
                    + S.charAt(i + pattern.length()) - 'A';
        }
    }
  
    // Method 2
    // Main driver method
    public static void main(String[] args)
    { 
        
        // Input string to be traversed
        String S = "CACCACA";
  
        // Pattern string to be checked
        String pattern = "CAC";
  
        // Calliing the above search() method(Method1)
        // in the main() method
        search(S, pattern);
    }
}
输出
0
3