将两个二进制数组与阈值进行比较(近似匹配)

时间:2015-08-23 16:53:18

标签: c++ algorithm performance pattern-matching string-matching

我有两个二进制数组,一个大小为34(模式),另一个大小为10000(目标)。  我想看看目标中是否有任何具有阈值的模式(例如最多4个不匹配)  并返回匹配数(不发生叠加,如果一个匹配则下一个匹配将远离800个单元)。  我知道这是一种近似匹配问题,但我不知道使用哪种算法具有最佳性能。到目前为止我所做的事情:(方法2有更好的表现)

void compare (bool *target, int t, bool * pattern , int p , int threshold)
{
    for(int i =0;i<t-p;i++){
        if(like(target+i,pattern,p,threshold)){
            return true;
        }
    }
    return false;
}

void like2(bool *target, bool * pattern , int p , int threshold){
    int k =0;
    for(int i =0;i<p, ;i++){
        k+= target[i] ^ pattern [i];
    }
    return (k<=threshold);
}
void like(bool *target, bool * pattern , int p , int threshold){
    int k =threshold;
    for(int i =0;i<p,k>=0 ;i++){
        if(target[i]!=pattern[i]){
            --k;
        }
    }
    return (k >=0);
}

我尝试使用字符串匹配算法,例如Knuth-Morris-Pratt算法,但它们是完全匹配的,将它们更改为近似匹配算法是一种困难的方法。

1 个答案:

答案 0 :(得分:3)

将模式组合成(长)整数pattern_int,因为它只有34位。现在循环target。在k = 0,您将模式的target位0-33组合到combined_int。当您按照以下方式进入k + 1重新计算combined_int时:

combined_int = (combined_int << 1) & ~(1 << 34) | target[k + 34];

基本上,你将它移动一个位置(因为你从k前进到k + 1),清除不再有位并添加一个新位置。

查看匹配是否“足够接近”模式,XOR combined_intpattern_int和计数1位。我相信后者是在现代CPU的单指令中完成的。

编辑:构建初始组合时,请确保pattern[0]最终为pattern_int中的最高位,同样为target。否则,您需要更改combined_int相应重新计算的方式。