给定两个字符串text和长度分别为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 ) )
高效方法:上述方法可以使用动态规划进行优化。以下是递推关系:
- 初始化一个二维数组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] 。
- 如果模式 [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
Javascript
Yes
时间复杂度: O(M * N)
辅助空间: O(M * N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。