我想匹配像Colibri这样的文件名。我试图通过正则表达式解决它。
在Colibri中搜索可以输入您在文件名中按顺序键入的字符,并在文件名中按顺序查找所有具有这些字符的文件。例如,对于“ab”,它找到“cabal”,“ab”和“achab”。
在字母之间简单插入.*
有效(所以搜索字符串“ab”变为正则表达式.*a.*b.*
),但我想在大量文件上进行。
到目前为止,我有O(N * ???),其中N是文件名的数量和???最好是线性复杂度(我假设我的语言使用NFA)。我不太关心空间复杂性。我应该选择哪些数据结构或算法来提高效率(时间复杂度)?
答案 0 :(得分:5)
如果您只想检查搜索字符串 search 的字符是否以相同的顺序包含在另一个字符串 str 中,您可以使用这个简单的算法:< / p>
pos := -1
for each character in search do
pos := indexOf(str, character, pos+1)
if pos is -1 then
break
endif
endfor
return pos
此算法返回 str 中 search 的最后一个字符的偏移量,否则返回-1。它的运行时在O( n )中(您可以用简单的indexOf
循环替换while
,该循环比较来自的 str 中的字符pos 到Length( str ) - 1并返回偏移量或-1)。
答案 1 :(得分:4)
如果用字符否定替换.
,它将大大提高您的效率。即。
[^a]*a[^b]*b.*
这样你就可以减少回溯。 See This Reference
编辑* @yi_H你是对的,这个正则表达式可能同样适用:
a[^b]*b
答案 2 :(得分:2)
您的.
是不必要的。如果只是转换“abc”,你会获得更好的性能
进入^[^a]*a[^b]*b[^c]*c
。
string exp = "^";
foreach (char c in inputString)
{
string s = Regex.Escape (c.ToString()); // escape `.` as `\.`
exp += "[^" + s + "]*" + s; // replace `a` with `[^a]*a`
}
Regex regex = new Regex (exp, RegexOptions.IgnoreCase);
foreach (string fileName in fileNames)
{
if (regex.IsMatch (fileName))
yield return fileName;
}
答案 3 :(得分:1)
对于有限的字符集,创建包含匹配文件名的数组或链表的查找表可能是有意义的。
如果您的ABC包含X个字符,那么“1长度”查找表将包含X表条目,如果它是“2长度”表,则它将包含X ^ 2个条目,依此类推。 2长度表将包含每个条目(“ab”,“qx”)所有具有该顺序的字母的文件。当搜索更长的输入“string”时,查找相应的条目并对这些条目进行搜索。
注意:计算所需的额外内存并测量速度提升(与全表扫描相比),优势取决于数据集。