编程语言
首页 > 编程语言> > 字符串解析和匹配算法

字符串解析和匹配算法

作者:互联网

我正在解决以下问题:

假设我有一个软件包列表,它们的名称可能看起来像这样(唯一已知的是,这些名称的格式类似于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表示版本正则表达式工作时间.

但是,我怀疑有更好的解决方案(总是存在!),也许是特定的数据结构或更好的匹配方法.

如果您可以对当前方法提出建议或做一些注释,请不要犹豫.

解决方法:

这个怎么样? (伪代码)

Dictionary<string,string> latestPackages=new Dictionary<string,string>(packageNameComparer);

foreach element
{
    (package,version)=applyRegex(element);

    if(!latestPackages.ContainsKey(package) || isNewer)
    {
        latestPackages[package]=version;
    }
}

//print out latestPackages

字典操作为O(1),因此您的运行时总数为O(n).无需预先分组,而不是存储所有匹配项,而仅存储当前最新的匹配项.

字典具有一个接受IEqualityComparer对象的构造函数.在那里,您可以实现自己的包名称之间相等的语义.但是请记住,您需要在此IEqualityComparer中实现GetHashCode方法,该方法应为您认为相等的对象返回相同的值.要重现上面的示例,您可以返回字符串中第一个字符的哈希码,这将重现您词典中的分组.但是,使用更智能的哈希代码(不会有太多冲突),您将获得更高的性能.如果仍能产生良好的效果,则可能使用更多字符.

标签:string-matching,version,string,c,algorithm
来源: https://codeday.me/bug/20191201/2083625.html