C# .Net简单正则表达式二次复杂度

C# .Net简单正则表达式二次复杂度,c#,.net,regex,time-complexity,backtracking,C#,.net,Regex,Time Complexity,Backtracking,在构建一个简单的regex时,我发现随着输入大小的增加,它有一个非常奇怪的性能 下面是另一个具有类似行为的真正基本正则表达式: a+b 我用一个简单的基准测试对其进行了分析: Regex regex = new Regex("a+b", RegexOptions.Compiled); const int maxInputSize = 100; const int n = 1000; string input = ""; Stopwatch stopwatch = new Stopwatch

在构建一个简单的regex时,我发现随着输入大小的增加,它有一个非常奇怪的性能

下面是另一个具有类似行为的真正基本正则表达式:

a+b
我用一个简单的基准测试对其进行了分析:

Regex regex = new Regex("a+b", RegexOptions.Compiled);

const int maxInputSize = 100;
const int n = 1000;

string input = "";
Stopwatch stopwatch = new Stopwatch();
for (int inputSize = 1; inputSize <= maxInputSize; ++inputSize)
{
    input += 'a';

    stopwatch.Restart();
    for (int i = 0; i < n; ++i)
    {
        regex.Match(input);
    }
    stopwatch.Stop();

    Console.WriteLine(stopwatch.Elapsed.Ticks);
}
因此,它应该执行类似于2n的操作

(本文档似乎证实了复杂性应该是线性的:)

但我观察到的是一种二次复杂性:

因此,我的问题是:

  • 1) 我对线性复杂性的期望是否不合理
  • 2) 如果是,我缺少关于正则表达式匹配的什么
  • 3) 如果没有,我的基准是否有缺陷?为什么?
  • 4) 如果我的期望和基准是正确的,那么会出现什么问题

提前感谢您的输入。

函数
Regex.Match
搜索子字符串匹配:引擎尝试匹配从字符串的任何索引开始的表达式,给出一个O(n²)算法。通过将正则表达式锚定到字符串的开头,可能可以实现线性性能:

Regex regex = new Regex("^a+b$", RegexOptions.Compiled);

您可能希望在计时单位为秒的情况下增加样本量,而不是100的滴答声,因为您的时间提供者可能没有您预期的准确。@DarrenKopp:这句话不错,但在这种情况下,样本量与实验一致:它需要十分之一毫秒,即使样本量较大,我也会得到相同的行为。谢谢。实际上,在这个链接中,你指出了很多关于如何优化正则表达式和避免回溯等的建议。我认为在某些情况下,当然需要更复杂的语法!有了这个,我就有了一个线性复杂度,很明显为什么我的复杂度是二次的:在字符串上滑动窗口就是缺失的维度。谢谢你的快速回答。:)
Regex regex = new Regex("^a+b$", RegexOptions.Compiled);