Duas cadeias de comprimento k , diferindo em um caractere, compartilham um prefixo de comprimento l e um sufixo de comprimento m, de modo que k = l + m + 1 .
A resposta de Simon Prins codifica isso armazenando todas as combinações de prefixo / sufixo explicitamente, ou abc
seja *bc
, torna-se a*c
e ab*
. Isso é k = 3, l = 0,1,2 em = 2,1,0.
Como valarMorghulis aponta, você pode organizar as palavras em uma árvore de prefixos. Há também a árvore de sufixos muito semelhante. É bastante fácil aumentar a árvore com o número de nós de folhas abaixo de cada prefixo ou sufixo; isso pode ser atualizado em O (k) ao inserir uma nova palavra.
O motivo pelo qual você deseja essas contagens de irmãos é saber, com uma nova palavra, se deseja enumerar todas as cadeias com o mesmo prefixo ou se deve enumerar todas as cadeias com o mesmo sufixo. Por exemplo, para "abc" como entrada, os possíveis prefixos são "", "a" e "ab", enquanto os sufixos correspondentes são "bc", "c" e "". Como é óbvio, para sufixos curtos, é melhor enumerar irmãos na árvore de prefixos e vice-versa.
Como o @einpoklum aponta, certamente é possível que todas as strings compartilhem o mesmo prefixo k / 2 . Isso não é um problema para essa abordagem; a árvore do prefixo será linear até a profundidade k / 2, com cada nó até a profundidade k / 2 sendo o ancestral de 100.000 nós de folha. Como resultado, a árvore de sufixos será usada até (k / 2-1) de profundidade, o que é bom porque as strings precisam diferir em seus sufixos, uma vez que compartilham prefixos.
[edit] Como otimização, depois de determinar o prefixo único mais curto de uma string, você sabe que se houver um caractere diferente, ele deverá ser o último caractere do prefixo e você teria encontrado a duplicata quase quando verificando um prefixo mais curto. Portanto, se "abcde" tiver um prefixo único mais curto "abc", isso significa que existem outras strings que começam com "ab?" mas não com "abc". Ou seja, se eles diferissem em apenas um personagem, esse seria o terceiro personagem. Você não precisa mais verificar "abc? E".
Pela mesma lógica, se você achar que "cde" é um sufixo mais curto e exclusivo, saberá que precisa verificar apenas o prefixo comprimento 2 "ab" e não o prefixo comprimento 1 ou 3.
Observe que esse método funciona apenas para diferenças de exatamente um caractere e não generaliza para 2 diferenças de caracteres. Ele confia em um caractere, sendo a separação entre prefixos e sufixos idênticos.