计算两个字符串的相似程度

calculating how much two strings are similar?

本文关键字:字符串 相似 程度 两个 计算      更新时间:2023-10-16

我有一个函数,可以计算两个给定字符串的方差。有没有更快的方法(或算法)来做这件事?

请记住,我字符串中的每个字母都加载了DNA,这意味着这些是A、T、C或G中的一个:

unsigned __int8 dis(char* FirstString, char* SecondString)
{
    unsigned __int8 distanceIndex = 0;
    for (unsigned __int8 i = 0; i < l; i++)
    {
        if (FirstString[i] != SecondString[i])
            distanceIndex++;
    }
    return distanceIndex;
}

尽管我仍然怀疑字符串比较是否真的是您项目的瓶颈,但我还是忍不住接受了挑战。。。

你所有的序列都是13字符长。DNA序列只包含字母ATCG,可以在2位内编码。你可以将每个DNA序列存储在一个32位的值内,让计算机并行进行比较:

  • 对值进行XOR组合以获得位差
  • shift和OR组合and归一化子集(奇数位、偶数位)以将位差转化为核碱基差
  • 对设置的比特进行计数以获得DNA序列距离

根据计算机体系结构,可能有位计数功能在CPU中实现。更多的细节有问题的答案:如何计算32位中的设置位数整数

以下是核心功能:

int distV(const unsigned va, const unsigned vb)
{
    const unsigned x = va ^ vb;
    const unsigned bn = ((x & 0xaaaaaaaa) >> 1 ) | (x & 0x55555555);
    return __builtin_popcount(bn);
}

请参阅完整的GCC-4.3.2演示,该演示使用长度为16的序列。我测量了比较本身的性能增量因子4(不包括编码)。

这是一个O(n)算法。

比较两个字符串之间相等性(在这种情况下为距离)的最有效算法是O(n)。

您可以备用if:

unsigned __int8 dis(char* FirstString, char* SecondString)
{
    unsigned __int8 distanceIndex = 0;
    for (unsigned __int8 i = 0; i < l; i++)
       {
            distanceIndex += FirstString[i] != SecondString[i];
       }
    return distanceIndex;
}

但我怀疑这个重要的是否

您可以通过避免索引进行的随机访问来使其稍微快一点,实际上只需要对字符串进行顺序访问。

不过,我不确定编译器是否能为您优化它。