📌  相关文章
📜  检查给定字符串是否存在给定模式

📅  最后修改于: 2021-04-17 14:39:24             🧑  作者: Mango

给定两个字符串分别为长度为MN的文本模式,任务是检查模式是否文本匹配。如果发现是真的,则打印“是” 。否则,打印“否”

注意:模式可以包含字符“ *”“•”

  • 当前字符之前“*”匹配零个或多个字符权
  • ‘•’匹配任何信号字符。

例子:

天真的方法:解决此问题的最简单方法是使用递归遍历两个字符串的字符。如果当前字符为“。” ,将当前字符替换为任何字符,然后重复剩余的模式文本字符串。否则,如果当前字符为‘*’ ,请重复查找剩余的文本,并检查其是否与模式的其余部分匹配。如果发现是真的,则打印“是” 。否则,打印“否”

时间复杂度: O((M + N)* 2 (M + N / 2) )
辅助空间: O((M + N)* 2 (M + N / 2) )

高效方法:可以使用动态编程来优化上述方法。以下是递归关系:

  • 初始化2D数组dp [M + 1] [N + 1] ,其中dp [i] [j]检查子字符串{text [0],…,text [i]}是否与子字符串{pattern [ 0],…pattern [j]}或不。
  • 遍历两个字符串的字符,并根据以下重复关系填充dp [] []数组:
    • 如果text [i]pattern [j]相同,则填充dp [i + 1] [j +1] = dp [i] [j]
    • 如果pattern [j]‘。然后填充dp [i + 1] [j + 1] = dp [i] [j]。
    • 如果pattern [j]‘*’,则检查以下条件:
      • 如果text [i]不等于pattern [j – 1]并且pattern [j – 1]不等于‘。 ,然后填充dp [i + 1] [j + 1] = dp [i + 1] [j – 1]
      • 否则,填充dp [i + 1] [j + 1] =(dp [i + 1] [j] || dp [i] [j + 1] || dp [i + 1] [j – 1])
  • 最后,打印dp [M] [N]的值

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to check if the pattern
// consisting of '*', '.' and lowercase
// characters matches the text or not
int isMatch(string text, string pattern)
{
 
  // Base Case
  if (text == "" or pattern == "")
    return false;
 
  // Stores length of text
  int N = text.size();
 
  // Stores length of pattern
  int M = pattern.size();
 
  // dp[i][j]: Check if { text[0], .. text[i] }
  // matches {pattern[0], ... pattern[j]} or not
  vector> dp(N + 1, vector(M + 1, false));
 
  // Base Case
  dp[0][0] = true;
 
  // Iterate over the characters
  // of the string pattern
  for (int i = 0; i < M; i++)
  {
    if (pattern[i] == '*'
        && dp[0][i - 1]) {
 
      // Update dp[0][i + 1]
      dp[0][i + 1] = true;
    }
  }
 
  // Iterate over the characters
  // of both the strings
  for (int i = 0; i < N; i++) {
 
    for (int j = 0; j < M; j++) {
 
      // If current character
      // in the pattern is '.'
      if (pattern[j] == '.') {
 
        // Update dp[i + 1][j + 1]
        dp[i + 1][j + 1] = dp[i][j];
      }
 
      // If current character in
      // both the strings are equal
      if (pattern[j]
          == text[i]) {
 
        // Update dp[i + 1][j + 1]
        dp[i + 1][j + 1] = dp[i][j];
      }
 
      // If current character
      // in the pattern is '*'
      if (pattern[j] == '*') {
 
        if (pattern[j - 1] != text[i]
            && pattern[j - 1] != '.') {
 
          // Update dp[i + 1][j + 1]
          dp[i + 1][j + 1] = dp[i + 1][j - 1];
        }
 
        else {
 
          // Update dp[i+1][j+1]
          dp[i + 1][j + 1] = (dp[i + 1][j]
                              or dp[i][j + 1]
                              or dp[i + 1][j - 1]);
        }
      }
    }
  }
 
  // Return dp[M][N]
  return dp[N][M];
}
 
// Driver Code
int main()
{
  string text = "geeksforgeeks";
  string pattern = "ge*ksforgeeks";
 
  if (isMatch(text, pattern))
    cout<<"Yes";
  else
    cout<<"No";
}
 
// This code is contributed by mohiy kumar 29.


Java
// Java program for the above approach
 
import java.io.*;
 
class GFG {
 
    // Function to check if the pattern
    // consisting of '*', '.' and lowercase
    // characters matches the text or not
    static boolean isMatch(String text,
                           String pattern)
    {
        // Base Case
        if (text == null || pattern == null) {
            return false;
        }
 
        // Stores length of text
        int N = text.length();
 
        // Stores length of pattern
        int M = pattern.length();
 
        // dp[i][j]: Check if { text[0], .. text[i] }
        // matches {pattern[0], ... pattern[j]} or not
        boolean[][] dp = new boolean[N + 1][M + 1];
 
        // Base Case
        dp[0][0] = true;
 
        // Iterate over the characters
        // of the string pattern
        for (int i = 0; i < M; i++) {
            if (pattern.charAt(i) == '*'
                && dp[0][i - 1]) {
 
                // Update dp[0][i + 1]
                dp[0][i + 1] = true;
            }
        }
 
        // Iterate over the characters
        // of both the strings
        for (int i = 0; i < N; i++) {
 
            for (int j = 0; j < M; j++) {
 
                // If current character
                // in the pattern is '.'
                if (pattern.charAt(j) == '.') {
 
                    // Update dp[i + 1][j + 1]
                    dp[i + 1][j + 1] = dp[i][j];
                }
 
                // If current character in
                // both the strings are equal
                if (pattern.charAt(j)
                    == text.charAt(i)) {
 
                    // Update dp[i + 1][j + 1]
                    dp[i + 1][j + 1] = dp[i][j];
                }
 
                // If current character
                // in the pattern is '*'
                if (pattern.charAt(j) == '*') {
 
                    if (pattern.charAt(j - 1) != text.charAt(i)
                        && pattern.charAt(j - 1) != '.') {
 
                        // Update dp[i + 1][j + 1]
                        dp[i + 1][j + 1] = dp[i + 1][j - 1];
                    }
 
                    else {
 
                        // Update dp[i+1][j+1]
                        dp[i + 1][j + 1] = (dp[i + 1][j]
                                            || dp[i][j + 1]
                                            || dp[i + 1][j - 1]);
                    }
                }
            }
        }
 
        // Return dp[M][N]
        return dp[N][M];
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        String text = "geeksforgeeks";
        String pattern = "ge*ksforgeeks";
 
        if (isMatch(text, pattern)) {
 
            System.out.println("Yes");
        }
        else {
 
            System.out.println("No");
        }
    }
}


Python3
# Python3 program for the above approach
import numpy as np
 
# Function to check if the pattern
# consisting of '*', '.' and lowercase
# characters matches the text or not
def isMatch(text, pattern):
     
  # Base Case
  if (text == "" or pattern == ""):
    return False
 
  # Stores length of text
  N = len(text)
 
  # Stores length of pattern
  M = len(pattern)
 
  # dp[i][j]: Check if { text[0], .. text[i] }
  # matches {pattern[0], ... pattern[j]} or not
  dp = np.zeros((N + 1, M + 1))
 
  # Base Case
  dp[0][0] = True
 
  # Iterate over the characters
  # of the string pattern
  for i in range(M):
    if (pattern[i] == '*' and dp[0][i - 1]):
 
      # Update dp[0][i + 1]
      dp[0][i + 1] = True
 
  # Iterate over the characters
  # of both the strings
  for i in range(N):
    for j in range(M):
 
      # If current character
      # in the pattern is '.'
      if (pattern[j] == '.'):
 
        # Update dp[i + 1][j + 1]
        dp[i + 1][j + 1] = dp[i][j]
 
      # If current character in
      # both the strings are equal
      if (pattern[j] == text[i]):
 
        # Update dp[i + 1][j + 1]
        dp[i + 1][j + 1] = dp[i][j]
 
      # If current character
      # in the pattern is '*'
      if (pattern[j] == '*'):
        if (pattern[j - 1] != text[i] and
            pattern[j - 1] != '.'):
 
          # Update dp[i + 1][j + 1]
          dp[i + 1][j + 1] = dp[i + 1][j - 1]
         
        else:
 
          # Update dp[i+1][j+1]
          dp[i + 1][j + 1] = (dp[i + 1][j] or
                              dp[i][j + 1] or
                              dp[i + 1][j - 1])
 
  # Return dp[M][N]
  return dp[N][M]
 
# Driver Code
if __name__ == "__main__" :
 
  text = "geeksforgeeks"
  pattern = "ge*ksforgeeks"
   
  if (isMatch(text, pattern)):
    print("Yes")
  else:
    print("No")
 
# This code is contributed by AnkThon


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Function to check if the pattern
// consisting of '*', '.' and lowercase
// characters matches the text or not
static bool isMatch(string text, string pattern)
{
     
    // Base Case
    if (text == null || pattern == null)
    {
        return false;
    }
 
    // Stores length of text
    int N = text.Length;
 
    // Stores length of pattern
    int M = pattern.Length;
 
    // dp[i][j]: Check if { text[0], .. text[i] }
    // matches {pattern[0], ... pattern[j]} or not
    bool[,] dp = new bool[N + 1, M + 1];
 
    // Base Case
    dp[0, 0] = true;
 
    // Iterate over the characters
    // of the string pattern
    for(int i = 0; i < M; i++)
    {
        if (pattern[i] == '*' && dp[0, i - 1])
        {
             
            // Update dp[0][i + 1]
            dp[0, i + 1] = true;
        }
    }
 
    // Iterate over the characters
    // of both the strings
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < M; j++)
        {
             
            // If current character
            // in the pattern is '.'
            if (pattern[j] == '.')
            {
                 
                // Update dp[i + 1][j + 1]
                dp[i + 1, j + 1] = dp[i, j];
            }
 
            // If current character in
            // both the strings are equal
            if (pattern[j] == text[i])
            {
                 
                // Update dp[i + 1][j + 1]
                dp[i + 1, j + 1] = dp[i, j];
            }
 
            // If current character
            // in the pattern is '*'
            if (pattern[j] == '*')
            {
                if (pattern[j - 1] != text[i] &&
                    pattern[j - 1] != '.')
                {
                     
                    // Update dp[i + 1][j + 1]
                    dp[i + 1, j + 1] = dp[i + 1, j - 1];
                }
 
                else
                {
                     
                    // Update dp[i+1][j+1]
                    dp[i + 1, j + 1] = (dp[i + 1, j] ||
                                        dp[i, j + 1] ||
                                        dp[i + 1, j - 1]);
                }
            }
        }
    }
 
    // Return dp[M][N]
    return dp[N, M];
}
 
// Driver Code
public static void Main()
{
    string text = "geeksforgeeks";
    string pattern = "ge*ksforgeeks";
 
    if (isMatch(text, pattern))
    {
        Console.WriteLine("Yes");
    }
    else
    {
        Console.WriteLine("No");
    }
}
}
 
// This code is contributed by ukasp


输出:
Yes

时间复杂度: O(M * N)
辅助空间: O(M * N)