public class Solution { public bool IsMatch(string s, string p) => IsMatch(null, s, p); private bool IsMatch(char? prev, ReadOnlySpan str, ReadOnlySpan 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 pattern) { if (pattern.Length % 2 == 1) return false; for (var i = 1; i < pattern.Length; i += 2) if (pattern[i] != '*') return false; return true; } }