确定满足汉明距离矩阵的字符串

3

我正在尝试从汉明距离矩阵中创建一个字符串列表。每个字符串必须是20个字符长,使用4个字母的字母表(A、B、C、D)。例如,假设我有以下汉明距离矩阵:

   S1 S2 S3
S1  0  5 12
S2  5  0 14
S3 12 14  0

我需要从这个矩阵中创建3个字符串,例如:

S1 = "ABBBBAAAAAAAAAABBBBB"
S2 = "BAAAAAAAAAAAAAABBBBB"
S3 = "CBBBABBBBBBBBBBBBBBB"

我手动创建了这些字符串,但是对于表示100个字符串的汉明距离矩阵来说,手动操作是不切实际的。有没有人能建议一个可以做到这一点的算法?

谢谢,Chris

1个回答

1

这是一个有趣的练习。:-)

以下octave脚本随机生成长度为lenn个字符串。然后计算所有这些字符串之间的汉明距离。

接下来要做的是逐对比较字符串。例如,如果您搜索[5 12 14],您将发现表N包含512之间以及1214之间的字符串。下一个挑战当然是找到电路,在该电路中可以将距离为512的字符串与距离为1214的字符串结合在一起,使电路“闭合”。

%我们生成长度为len的n个字符串
n = 50;
len = 20;
%我们有一个大小为4(ABCD)的分类变量 cat = 4;
%我们想要生成与以下海明距离矩阵对应的字符串 search = [5 12 14]; %search=[10 12 14 14 14 16]; S = squareform(search);
%请注意,我们完全随机生成每个字符串。如果需要小距离,则引入跨字符串的相关性是有意义的 X = randi(cat-1, n, len);
%计算海明距离 t = pdist(X,'hamming') * len;
%我们必须在其中找到我们的小矩阵S的大矩阵 Y = squareform(t);
%如果存在submatrix(Y,S),则所有以下内容都可能被替换为这样的东西 R = zeros(size(S), size(Y)); for j = 1:size(S) M = zeros(size(Y), size(S)); for i = 1:size(Y) M(i,:) = ismember(S(j,:), Y(i,:)); endfor R(j,:) = all(M'); endfor [x,y] = find(R);
%A将是包含将组成我们子矩阵的列/行的索引的单元格集合 A = accumarray(x,y,[], @(v) {sort(v).'});
%例如,如果根本不存在距离5,则我们可以直接退出 if (sum(cellfun(@isempty,A)) > 0) printf("没有匹配项\n"); return endif
%我们现在要获取所有具有“search”中的值的可能子矩阵 C = cell(1, numel(A)); [C{:}] = ndgrid( A{:} );
N = cell2mat( cellfun(@(v)v(:), C, 'UniformOutput',false) ); N = unique(sort(N,2), 'rows'); printf("找到%i个潜在匹配项(但包含重复项)\n", size(N,1));
%我们现在进一步过滤(删除重复项) [f,g] = mode(N,2); h = g == 1; N = N(h,:); printf("找到%i个潜在匹配项\n", size(N,1));
M = zeros(size(N), size(search,2)); for i = 1:size(N) f = N(i,:); M(i,:) = squareform(Y(f,f))'; endfor F = squareform(S)';
%目前我们忘记了错误的排列,因此对于search>3,您需要过滤掉这些! M = sort(M,2); F = sort(F,2);
%从(大)表M中取出已排序的搜索字符串 %我们搜索“关闭”电路的那些 D = ismember(M,F,'rows'); mf = find(D);
if (mf) matches = size(mf,1); printf("找到%i个匹配项\n", matches); for i = 1:matches r = mf(i); printf("我们返回匹配项%i(仅检查排列现在)\n", r); t = N(r,:)'; str = X(t,:); check = squareform(pdist(str,'hamming')*len); strings = char(str+64) check endfor else printf("没有匹配项\n"); endif
它将生成类似以下的字符串:
ABAACCBCACABBABBAABA
ABACCCBCACBABAABACBA
CABBCBBBABCBBACAAACC

谢谢Anne!这个方法确实有效,但当尝试处理更多字符串(11个字符串)时,Octave会抛出“内存不足”的错误。这是我第一次使用Octave,可能是我的无知,但具体来说,我使用了以下内容:search = [0 0 3 3 5 5 5 3 8 8 0 3 3 5 5 5 3 8 8 3 3 5 5 5 3 8 8 3 2 2 2 3 8 8 5 5 5 6 8 11 0 0 3 9 8 0 3 9 8 3 9 8 8 5 8],其中n=10000(我已经使用了较低的n,但返回“没有匹配项”)。 - ChrisUofR
@ChrisUofR。如果您想要使用指定的汉明距离矩阵生成100个字符串(或只略微更多),那么这个算法是非常有用的。您需要运行该算法>100次才能实现这一点。它不会每次都找到一组字符串;您需要运行它几次才能成功。对于一个11x11的矩阵,它将创建一个巨大的搜索空间,因此您需要找到一个优化的算法来解决这个问题。此外,像0、2和3这样的距离在当前的随机生成器中很少出现。因此,您还需要提供与 randi 不同的先验值来解决这个问题。 - Anne van Rossum
此外,你必须小心从哪里获取大矩阵。即使像 search=[10 0 0] 这样的小矩阵也无法求解:S_1S_2 不同且与 S_3 相同。然而,S_2S_3 相同,这就导致了矛盾。 - Anne van Rossum
我非常感谢你的帮助。我看到混淆在于我的措辞。我需要满足100x100海明距离矩阵的100个字符串。 - ChrisUofR
@ChrisUofR 我会先找到一种方法来检查这个100x100的汉明距离矩阵是否可解。我认为这个问题本身已经值得提出一个单独的问题了。 :-) - Anne van Rossum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接