【发布时间】:2012-02-20 00:14:00
【问题描述】:
我正在解决以下问题:
假设我有一个软件包列表,它们的名称可能如下所示(唯一已知的是这些名称的格式类似于SOMETHING + VERSION,这意味着版本总是在之后 名字):
Efficient.Exclusive.Zip.Archiver-PROPER.v.122.24-EXTENDED
Efficient.Exclusive.Zip.Archiver.123.01
Efficient-Exclusive.Zip.Archiver(2011)-126.24-X
Zip.Archiver14.06
Zip-Archiver.v15.08-T
Custom.Zip.Archiver1.08
Custom.Zip.Archiver1
现在,我需要解析这个列表并只选择每个包的最新版本。对于这个例子,预期的结果是:
Efficient-Exclusive.Zip.Archiver(2011)-126.24-X
Zip-Archiver.v15.08-T
Custom.Zip.Archiver1.08
我目前使用的方法可以这样描述:
Split the initial strings into groups by their starting letter,
ignoring spaces, case and special symbols.
(`E`, `Z`, `C` for the example list above)
Foreach element {
Apply the regular expression (or a set of regular expressions),
which tries to deduce the version from the string and perform
the following conversion `STRING -> (VERSION, STRING_BEFORE_VERSION)`
// Example for this step:
// 'Efficient.Exclusive.Zip.Archiver-PROPER.v.122.24-EXTENDED' ->
// (122.24, Efficient.Exclusive.Zip.Archiver-PROPER)
Search through the corresponding group (in this example - the 'E' group)
and find every other strings, which starts from the 'STRING_BEFORE_VERSION' or
from it's significant part. This comparison is performed in ignore-case and
ignore-special-symbols mode.
// The matches for this step:
// Efficient.Exclusive.Zip.Archiver-PROPER, {122.24}
// Efficient.Exclusive.Zip.Archiver, {123.01}
// Efficient-Exclusive.Zip.Archiver, {126.24, 2011}
// The last one will get picked, because year is ignored.
Get the possible version from each match, ***pick the latest, yield that match.***
Remove every possible match (including the initial element) from the list.
}
这个算法(我假设)应该适用于O(N * V + N lg N * M),其中M 代表平均字符串匹配时间,V 代表版本正则表达式工作时间。
不过,我怀疑有更好的解决方案(总是有!),可能是特定的数据结构或更好的匹配方法。
如果您可以提出一些建议或对当前方法做一些说明,请不要犹豫。
【问题讨论】:
-
也许找到最长的公共子串会有所帮助? en.wikipedia.org/wiki/Longest_common_substring_problem。您可以在 SO 和 Web 的其他地方找到许多讨论和实现。
-
@Jim 最长公共子串问题有助于两个字符串之间的比较,但不能优化要完成的比较次数。我知道 OP 已经知道如何确定 2 个包是否相等,并且只想使用某种集群更快地做到这一点。
-
您的运行时分析是错误的:它是 O(N^2) 而不是 O(N log N) (去除了常数因子),因为您仅基于范围有限的第一个字符进行分组(字母表),然后将每个条目与同一组中的所有其他条目进行比较。
标签: c# string algorithm version string-matching