📜  矩阵中模式搜索的 Rabin-Karp 算法

📅  最后修改于: 2021-09-04 11:19:58             🧑  作者: Mango

给定维度为m1 x m2 的矩阵txt[][]和维度为n1 x n2 的模式pat[][] ,任务是检查矩阵中是否存在模式,如果是,则打印顶部的 mot 索引txt[][] 中的pat[] [] 。假设m1, m2 ≥ n1, n2
例子:

Input:
txt[][] = {{G, H, I, P}
           {J, K, L, Q}
           {R, G, H, I}  
           {S, J, K, L}
          }
pat[][] = {{G, H, I},
           {J, K, L}
          }
Output:
Pattern found at ( 0, 0 )
Pattern found at ( 2, 1 )
Explanation:


Input:
txt[][] = { {A, B, C},
            {D, E, F},
            {G, H, I}
          }
pat[][] = { {E, F},
            {H, I}
          }
Output:
Pattern found at (1, 1)

方法:为了使用 Rabin-Karp 算法在二维数组中找到模式,请考虑输入矩阵txt[m1][m2]和模式pat[n1][n2] 。这个想法是找到mat[][]pat[][]的每一列的哈希值并比较哈希值。对于任何列,如果哈希值等于,则检查相应的行值。以下是步骤:

  1. 找出txt[][]pat[][]矩阵中前N1行的每一列的哈希值。
  2. 通过查找在步骤 1 中找到的列哈希的哈希值来应用 Rabin-Karp 算法。
  3. 如果找到匹配项,则比较特定行和列的txt[][]pat[][]矩阵。
  4. 否则,使用滚动散列将 txt 矩阵中的列散列向下滑动 1 行。
  5. 重复步骤2至4对所有的哈希值,如果我们发现任何拍拍[] []匹配在TXT [] []然后打印最上面的单元格的指数在TXT [] []。

查找散列值:为了使用滚动散列在文本中查找大小为N的子串的散列值,请执行以下步骤:

  1. 从字符串删除第一个字符: hash(txt[s:s+n-1])-(radix**(n-1)*txt[s])%prime_number
  2. 将下一个字符添加到字符串: hash(txt[s:s+n-1])*radix + txt[n]

下面是上述方法的实现:

Python3
# Python implementation for the
# pattern matching in 2-D matrix
 
# Function to find the hash-value
# of the given columns of text
def findHash(arr, col, row):
    hashCol = []
    add = 0
    radix = 256
 
    # For each column
    for i in range(0, col):
 
        for j in reversed(range(0, row)):
            add = add + (radix**(row-j-1) *
                         ord(arr[j][i]))% 101
        hashCol.append(add % 101);
        add = 0
    return hashCol
 
# Function to check equality of the
# two strings
def checkEquality(txt, row, col, flag):
    txt = [txt[i][col:patCol + col]
           for i in range(row, patRow + row)]
 
# If pattern found
    if txt == pat:
        flag = 1
        print("Pattern found at", \
              "(", row, ", ", col, ")")
    return flag
     
# Function to find the hash value of
# of the next column using rolling-hash
# of the Rabin-karp
def colRollingHash(txtHash, nxtRow):
 
    radix = 256
 
    # Find the hash of the matrix
    for j in range(len(txtHash)):
        txtHash[j] = (txtHash[j]*radix \
                      + ord(txt[nxtRow][j]))% 101
        txtHash[j] = txtHash[j] - (radix**(patRow) *
                     ord(txt[nxtRow-patRow][j]))% 101
        txtHash[j] = txtHash[j]% 101
    return txtHash
     
 
# Function to match a pattern in
# the given 2D Matrix
def search(txt, pat):
     
# List of the hashed value for
    # the text and pattern columns
    patHash = []
    txtHash = []
 
    # Hash value of the
    # pat_hash and txt_hash
    patVal = 0
    txtVal = 0
 
    # Radix value for the input characters
    radix = 256
     
    # Variable to determine if
    # pattern was found or not
    flag = 0
     
    # Function call to find the
    # hash value of columns
    txtHash = findHash(txt, txtCol, patRow) 
    patHash = findHash(pat, patCol, patRow)
     
    # Calculate hash value for patHash
    for i in range(len(patHash)):
        patVal = patVal \
                 + (radix**(len(patHash)-i-1) *
                 patHash[i]% 101)
    patVal = patVal % 101
     
     
    # Applying Rabin-Karp to compare
    # txtHash and patHash
    for i in range(patRow-1, txtRow):
        col = 0
        txtVal = 0
         
        # Find the hash value txtHash
        for j in range(len(patHash)):
            txtVal = txtVal\
                     + (radix**(len(patHash)-j-1) *
                     txtHash[j])% 101
        txtVal = txtVal % 101
         
        if txtVal == patVal:
            flag = checkEquality(\
                     txt, i + 1-patRow, col, flag)
             
        else:
 
            # Roll the txt window by one character
            for k in range(len(patHash), len(txtHash)):
 
                txtVal = txtVal \
                         * radix + (txtHash[k])% 101
                txtVal = txtVal \
                         - (radix**(len(patHash)) *
                         (txtHash[k-len(patHash)]))% 101
                txtVal = txtVal % 101
                col = col + 1
 
                # Check if txtVal and patVal are equal
                if patVal == txtVal:
                    flag = checkEquality(\
                           txt, i + 1-patRow, col, flag)  
                else:
                    continue
                 
        # To make sure i does not exceed txtRow
        if i + 1


C++
//C++ implementation of Rabin Karp for matrix
 
#include 
using namespace std;
long long mod = 257;
long long r = 256;
long long dr = 1;
long long dc = 1;
long long power(int a,int n,long long m){
  if(n == 0){
    return 1;
  }
  if(n == 1){
    return a%m;
  }
  long long pow = power(a,n/2,m);
  if(n&1){
    return ((a%m)*(pow)%m * (pow)%m)%m;
  }
  else{
    return ((pow)%m * (pow)%m)%m;
  }
}
 
bool check(vector> &txt,vector> &pat, long long r,long long c){
  for(long long i=0;i findHash(vector> &mat,long long row){
  vector hash;
  long long col = mat[0].size();
  for(long long i=0;i> &txt, vector &t_hash, long long row, long long p_row){
  for(long long i=0;i> &txt, vector> &pat){
  long long t_row = txt.size();
  long long t_col = txt[0].size();
  long long p_row = pat.size();
  long long p_col = pat[0].size();
  dr = power(r,p_row-1,mod);
  dc = power(r,p_col-1,mod);
  vector t_hash = findHash(txt,p_row);
  vector p_hash = findHash(pat,p_row);
  long long p_val = 0;
  for(long long i=0;i> txt{{'A','B','C','D','E'},{'A','B','C','D','E'},{'A','B','C','D','E'},{'A','B','C','D','E'},{'A','B','C','D','E'}};
  vector> pat{{'A','B','C','D','E'},{'A','B','C','D','E'},{'A','B','C','D','E'},{'A','B','C','D','E'}};
  rabinKarp(txt,pat);
  return 0;
}


输出
Pattern found at ( 1 ,  1 )

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live