Maior subsequência comum

Fonte: testwiki
Saltar para a navegação Saltar para a pesquisa

Predefinição:Wikificação O problema da maior subsequência comum(LCS) é sobre achar a maior subsequência em todas as sequências em um conjunto de sequências(normalmente duas). O problema da maior subsequência comum é um clássico da ciência da computação, é a base de programas de comparação de dados como o diff, e tem aplicações em computação linguística e bioinformática. Também é amplamente usado em sistemas de versionamento como Git para mesclar múltiplas mudanças feitas em arquivos.

Por exemplo, considere as sequências ABCD e ACBAD. Ambos têm 5 subsequências comuns de tamanho 2: AB, AC, BD e CD; e 2 subsequências comuns de tamanho 3: ABD e ACD. Então ABD e ACD são as maiores subsequências comuns.

Complexidade

Para os casos gerais de um número arbitrário de sequências, o problema é NP-difícil(veja complexidade de tempo)[1]. E quando o número de sequências é constante, pode ser resolvido em tempo polinomial com uso da programação dinâmica.

Dado N sequências de tamanho n1,...,nN, uma pesquisa pode testar cada uma das 2n1 subsequências da primeira sequência para determinar se é também subsequência das sequências restantes; cada subsequência pode ser testada em tempo linear nos tamanhos das sequências, então o tempo para isso seria:

O(2n1i>1ni)

Para o caso das 2 sequências de n e m elementos, o tempo de processamento usando a programação dinâmica seria O(nm). Para um número arbitrário de sequências, a programação dinâmica nos daria a solução em

O(Ni=1Nni)

Existem métodos com menor complexidade[2], que geralmente necessitam do tamanho do LCS, ou tamanho do alfabeto quando não ambos.

O LCS não é necessariamente exclusivo; no pior caso, o número de subsequências comuns é exponencial nos tamanhos das sequências, então a complexidade deve ser pelo menos exponencial.

Solução para duas sequências

O problema LCS tem uma estrutura ideal: o problema pode ser quebrado em partes menores; problemas mais simples, que podem ser quebrados em menores; e então, a solução se torna trivial. O LCS em particular permite que soluções complexas possam ser quebradas em soluções mais simples e reutilizáveis. Problemas com essas características podem ser abordados com a programação dinâmica, em que as soluções para problemas menores podem ser memorizadas e reutilizadas

Prefixos

O prefixo Sn de S é definido como os n primeiros caracteres de S[3]. Por exemplo, os prefixos de S=AGCA são:

S0=nenhum

S1=A

S2=AG

S3=AGC

S4=AGCA

Considere que LCS(X,Y) seja uma função que compute a maior subsequência comum de X e Y. Esta função tem duas propriedades muito interessantes.

Primeira propriedade

LCS(X^A,Y^A)=LCS(X,Y)^A, para todas as strings X, Y e todos os símbolos A, onde '^' representa a concatenação de strings. Isso permite simplificar o processo de LCS para as duas sequências que terminam com o mesmo símbolo. Por exemplo, LCS("BANANA","ATANA") = LCS("BANAN","ATAN")^A, continuam com o mesmo símbolo comum, LCS("BANANA","ATANA") = LCS("BAN","AT")^"ANA".

Segunda propriedade

Se A e B são símbolos distintos (AB), então LCS(X^A,Y^B) é uma das strings de tamanho máximo no conjunto {LCS(X^A,Y),LCS(X,Y^B)}, para todas as strings X, Y.

Por exemplo, LCS ("ABCDEFG", "BCDGK") é a sequência mais longa de <mathLCS ("ABCDEFG", "BCDG") e LCS ("ABCDEF", "BCDGK"); se ambos tivessem o mesmo comprimento, um deles poderia ser escolhido arbitrariamente.

Para prosseguir, diferencie os dois casos:

Se LCS ("ABCDEFG", "BCDGK") termina com um "G", então o "K" final não pode estar no LCS, portanto LCS ("ABCDEFG", "BCDGK") = LCS ("ABCDEFG", "BCDG ").

Se LCS ("ABCDEFG", "BCDGK") não terminar com um "G", então o "G" final não pode estar no LCS, portanto, LCS ("ABCDEFG", "BCDGK") = LCS ("ABCDEF", "BCDGK").

Definição da função

Considere duas sequências definidas da seguinte forma: X=(x1,X2,...,Xm) e Y=(Y1,Y2,...,Yn). Os prefixos de X são X1,X2,...,m; os prefixos de Y são Y1,Y2,...,n. Considere que LCS(Xi,Yj) represente o conjunto das maiores subsequências comuns dos prefixos Xi e Yj. Esse conjunto de subsequências é dado por:

𝐿𝐶𝑆(Xi,Yj)={se i=0 ou j=0𝐿𝐶𝑆(Xi1,Yj1)^xise i,j>0 e xi=yjmax{𝐿𝐶𝑆(Xi,Yj1),𝐿𝐶𝑆(Xi1,Yj)}se i,j>0 e xiyj

Para achar o LCS de Xi e Yj, compare xi e yj. Se forem iguais, então a sequência LCS(Xi1,Yj) é estendida pelo elemento xi. Se não forem iguais, então a mais longa das duas sequências, LCS(Xi,Yj1) e LCS(Xi1,Yj) é retida. (Se forem do mesmo tamanho mas não idênticas, ambas serão retidas)