медленное решение для 10. Regular Expression Matching

This commit is contained in:
2026-03-24 01:04:03 +03:00
parent 6c9412cc14
commit e6107b6dca
4 changed files with 113 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>_10._Regular_Expression_Matching</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,29 @@
var solution = new Solution();
var examples = new (string s, string p, bool expected)[]
{
("aa", "a", false),
("aa", "a*", true),
("ab", ".*", true),
("aab", "c*a*b", true),
("mississippi", "mis*is*p*.", false),
("mississippi", "mis*is*ip*.", true),
("aaa", "a*a", true),
("aaa", "ab*a*c*a", true),
("ab", ".*c", false),
("", "c*", true),
("abcd", "d*", false),
("", "", true),
("a", ".", true),
("", "a*", true),
("aa", "b*a*", true),
("a", "ab*", true),
("abcaaaaaaabaabcabac", ".*ab.a.*a*a*.*b*b*", true),
("", "a*b*", true),
};
foreach (var example in examples)
{
var result = solution.IsMatch(example.s, example.p);
Console.WriteLine($"s = \"{example.s}\", p = \"{example.p}\" => {result} (expected {example.expected})");
}

View File

@@ -0,0 +1,59 @@
public class Solution
{
public bool IsMatch(string s, string p) => IsMatch(null, s, p);
private bool IsMatch(char? prev, ReadOnlySpan<char> str, ReadOnlySpan<char> pattern)
{
if (pattern.Length == 0 && str.Length == 0)
return true;
if (str.Length == 0)
{
if (CanBeEmpty(pattern))
return true;
return false;
}
if (pattern.Length == 0)
return false;
var sym = str[0];
var p = pattern[0];
// раскрытая звёздочка
var pSymOrDot = p == '*' ? prev : p; // превращаем звёздочку в символ или точку
// ожидаемый текущий символ, конкретный
var pSym = pSymOrDot == '.' ? sym : pSymOrDot;
// следующий символ *
if (pattern.Length > 1 && pattern[1] == '*')
{
var match = false;
var i = 0;
do
{
match |= IsMatch(i > 0 ? p : prev, str[i..], pattern[2..]);
if (match || i == str.Length || str[i] != p && p != '.')
break;
i++;
}
while (i <= str.Length);
return match;
}
else if (sym != pSym)
{
return false;
}
else
{
return IsMatch(pSymOrDot, str[1..], pattern[1..]);
}
}
private bool CanBeEmpty(ReadOnlySpan<char> pattern)
{
if (pattern.Length % 2 == 1)
return false;
for (var i = 1; i < pattern.Length; i += 2)
if (pattern[i] != '*')
return false;
return true;
}
}