Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计算字符串的所有1-hamming距离邻居的最快方法?_Java_String_Hamming Distance - Fatal编程技术网

Java 计算字符串的所有1-hamming距离邻居的最快方法?

Java 计算字符串的所有1-hamming距离邻居的最快方法?,java,string,hamming-distance,Java,String,Hamming Distance,我试图计算n个节点组成的图中每个节点之间的汉明距离。此图中的每个节点都有一个相同长度(k)的标签,用于标签的字母表为{0,1,*}。“*”用作不在乎符号。例如,标签101*01和1001*1之间的汉明距离等于1(我们说它们只在第三个索引处不同) 我需要做的是找到每个节点的所有1-hamming距离邻居,并准确地报告这两个标签不同的索引 我将每个节点标签与所有其他字符逐个进行比较,如下所示: // Given two strings s1, s2 // returns the in

我试图计算n个节点组成的图中每个节点之间的汉明距离。此图中的每个节点都有一个相同长度(k)的标签,用于标签的字母表为{0,1,*}。“*”用作不在乎符号。例如,标签101*01和1001*1之间的汉明距离等于1(我们说它们只在第三个索引处不同)

我需要做的是找到每个节点的所有1-hamming距离邻居,并准确地报告这两个标签不同的索引

我将每个节点标签与所有其他字符逐个进行比较,如下所示:

    // Given two strings s1, s2
    // returns the index of the change if hd(s1,s2)=1, -1 otherwise.

    int count = 0;
    char c1, c2;
    int index = -1;

    for (int i = 0; i < k; i++)
    {
        // do not compute anything for *
        c1 = s1.charAt(i);
        if (c1 == '*')
            continue;

        c2 = s2.charAt(i);
        if (c2 == '*')
            continue;

        if (c1 != c2)
        {
            index = i;
            count++;

            // if hamming distance is greater than 1, immediately stop
            if (count > 1)
            {
                index = -1;
                break;
            }
        }
    }
    return index;
//给定两个字符串s1、s2
//如果hd(s1,s2)=1,则返回更改的索引,否则返回-1。
整数计数=0;
字符c1,c2;
int指数=-1;
for(int i=0;i1)
{
指数=-1;
打破
}
}
}
收益指数;
我可能有几百万个节点。k通常在50左右。我使用的是JAVA,这种比较需要n*n*k时间,而且运行速度很慢。我考虑过使用trys和VP树,但无法确定哪种数据结构适用于这种情况。我也研究了Simmetrics库,但什么也没有闪过我的脑海。如果有任何建议,我将不胜感激。

尝试以下方法:

将键转换为三元数(基数3)。i、 e.0=0,1=1,*=2 10位三值表示0..59049的范围,适合16位

这意味着其中两个将形成一个32位字。创建一个包含40亿个条目的查找表,这些条目返回两个10位三值字之间的距离

现在可以使用查找表在一次查找中检查密钥的10个字符。如果使用5个字符,那么3^5将为您提供243个值,这些值将适合一个字节,因此查找表将仅为64 KB

通过使用shift操作,可以创建不同大小的查找表,以平衡内存和速度

这样,您可以优化循环以更快地中止

要获取第一个差异的位置,可以使用第二个查找表,该表包含两个键子字符串的第一个差异的索引


如果有数百万个节点,那么将有许多节点以相同的子字符串开头。尝试将它们排序到bucket中,其中一个bucket包含以相同键开头的节点。这里的目标是使桶尽可能小(以减少n*n)。

有趣的问题。要不是外卡符号,这很容易

如果通配符是字母表中的常规字符,那么对于给定字符串,可以枚举所有k hamming distance 1字符串。然后在多重映射中查找这些字符串。比如101,你查001111和100

“不在乎”符号使其无法进行查找。但是,如果构建多重映射,使每个节点都由其所有可能的键存储,则可以再次执行该查找。因此,例如,1×1被存储为111和101。所以当你查找10*时,你会查找00001011001111,它会找到111存储的1*1

这样做的好处是,您可以将所有标签存储为整数,而不是三元结构,因此使用int[3]作为键值,您可以使用任何k<96

性能将取决于多重映射的支持实现。理想情况下,对于小于32的键,您应该使用散列实现,对于以上任何内容,您都应该使用树实现。通过树实现,所有节点都可以连接到
O(n*k*log(n))
中距离为1的邻居。构建多重映射需要
O(n*2^z)
其中
z
是任何字符串的最大通配符数。如果通配符的平均数较低,这应该是一个可接受的性能损失

编辑:您还可以通过将hamming distance 1邻居插入到多重贴图中,将所有节点的查找性能提高到
O(n*log(n))
,但这可能会扩大其大小


注意:我在午休时间打这个。我还没有检查详细信息。

存储1位掩码和*位掩码,而不是/附加到字符串中。可以使用位集,但让我们尝试不使用位集

static int mask(String value, char digit) {
    int mask = 0;
    int bit = 2; // Start with bits[1] as per specification.
    for (int i = 0; i < value.length(); ++i) {
        if (value.charAt(i) == digit) {
            mask |= bit;
        }
        bit <<= 1;
    }
    return mask;
}

class Cell {
    int ones;
    int stars;
}

int difference(Cell x, Cell y) {
    int distance = 0;
    return (x.ones & ~y.stars) ^ (y.ones & ~x.stars);
}

int hammingDistance(Cell x, Cell y) {
    return Integer.bitCount(difference(x, y));
}

boolean differsBy1(Cell x, Cell y) {
    int diff = difference(x, y);
    return diff == 0 ? false : (diff & (diff - 1)) == 0;
}

int bitPosition(int diff) {
    return Integer.numberOfTrailingZeroes(diff);
}
静态整数掩码(字符串值,字符数字){
int-mask=0;
int bit=2;//根据规范以位[1]开始。
对于(int i=0;i谢谢你的回答。我正在考虑如何使用查找表。它只有在我预先计算的情况下才有优势。因为我只需要一次距离。但是,字符串大小(k)不是一个固定的数字。对于我的测试,它的值介于4和75之间。我不知道如何确定大小。此外,bucket sort还有一个最坏的性能,即n*n。我是否缺少一个点?您可以在结尾处用
0
填充较短的键;这将保持第一次更改的距离和索引相同。对于较长的键,您必须d将它们拆分并进行多次查找。对于bucket排序,您可以使用哈希映射,其中键是节点键的长度(如果两个节点键的长度相差超过1位,则它们的汉明距离必须大于2)。在这些bucket中,您可以按键的前M位进行排序/哈希。这应该会给您O(N)对于bucket准备。我尝试使用查找表,但由于内存限制,我能够为5位标签创建一个查找表。不幸的是,此操作似乎比以前的操作慢2-3倍