编程语言
首页 > 编程语言> > C#-.net简单正则表达式二次复杂度

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

作者:互联网

在构建简单的正则表达式时,我发现它在输入大小增加的情况下具有非常奇怪的性能.

这是另一个具有类似行为的真正正则表达式:

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);
}

它在字符串“ a”,“ aa”,“ aaa”,…上运行正则表达式,并测量字符串的每个长度进行n次匹配所花费的时间.

我知道回溯问题(例如,如果正则表达式是(a a)b之类的东西),但是在这种情况下,即使考虑回溯,我也期望线性复杂度.

例如,如果我们要匹配n次“ a”,这是我天真的期望的工作流程:

take first 'a'
take second 'a'
...
take last 'a'
ooops nothing more to take => backtracking
release one 'a' and try to match 'b', nothing => backtracking
...
release second 'a' and retry to match 'b', nothing => backtracking
release first 'a'
ooops we're back at the beginning => no match

因此,它应该执行类似2n的操作.

(此文档似乎确认复杂度应该是线性的:http://msdn.microsoft.com/en-us/library/dsy130b4.aspx)

但是我却观察到二次复杂性:

所以我的问题是:

> 1)我对线性复杂度的期望不合理吗?
> 2)如果是,我在正则表达式匹配方面缺少什么?
> 3)如果否,我的基准测试是否有缺陷?为什么?
> 4)如果我的期望和基准是正确的,可能是什么问题?

预先感谢您的任何投入.

解决方法:

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

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

标签:backtracking,time-complexity,c,net,regex
来源: https://codeday.me/bug/20191030/1967148.html