给定两个字符串分别为长度为M和N的文本和模式,任务是检查模式是否与文本匹配。如果发现是真的,则打印“是” 。否则,打印“否” 。
注意:模式可以包含字符“ *”和“•”
- 当前字符之前“*”匹配零个或多个字符权
- ‘•’匹配任何信号字符。
例子:
Input: pattern = “ge*ksforgeeks”, text = “geeksforgeeks”
Output: Yes
Explanation:
Replacing * with ‘e’, modifies pattern equal to “geeksforgeeks”.
Therefore, the required output is Yes.
Input: pattern = “ab*d”, text = “abcds”
Output: No
Explanation: The given pattern cannot be matched with the text.
天真的方法:解决此问题的最简单方法是使用递归遍历两个字符串的字符。如果当前字符为“。” ,将当前字符替换为任何字符,然后重复剩余的模式和文本字符串。否则,如果当前字符为‘*’ ,请重复查找剩余的文本,并检查其是否与模式的其余部分匹配。如果发现是真的,则打印“是” 。否则,打印“否” 。
时间复杂度: 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)