Subseqüência mais longa sem string

8

Existe um algoritmo de programação dinâmica para encontrar a subsequência mais longa em uma string X que não contém Y como substring? Só que esse problema parece tão semelhante a outros algoritmos de cadeia de caracteres DP, como a subsequência e a seqüência comum mais longas. Ele deve ser capaz de lidar com ocorrências de Y que se sobrepõem.

Parece que esse pode ser um problema de DP de dois estados, com o estado [s_pos, t_pos] sendo a subsequência mais longa da sequência S iniciando em s_pos que não possui T [t_pos..M] como substring. N é o comprimento da cadeia S e M é o comprimento da cadeia T. No entanto, minhas transições não estão corretas: não obtém o caso em que S = aaabce T = aabc. O problema está na declaração else - não sei como fazer a transição se os caracteres forem iguais. Na verdade, eu sinto que o ramo se está errado ... alguém sabe o que pode estar errado?

Até falha no caso S = aaabe T = aab. Eu posso explicar por que ele falha: supondo que eu chame de resolver (0, 0). resolver (0, 0) chama resolver (1, 1). resolver (1, 1) chama resolver (2, 2). Como s [2]! = T [2], reinicia a pesquisa a partir da resolução (3, 0). No entanto, aab é uma substring e nunca verifica isso ou considera esse caso ...

int solve(int s_pos, int t_pos)
{
    if (s_pos >= N || t_pos >= M) return 0;
    if (t_pos == M - 1 && s[s_pos] == t[t_pos]) return 0;
    int ret = 0;
    if (s[s_pos] != t[t_pos])
    {
        int tmp = solve(s_pos + 1, 0);
        ret = max(ret, tmp + 1);
    }
    else
    {
        for (int i = s_pos + 1; i < N; i++)
        {
            int tmp = solve(i, t_pos + 1);
            if (tmp != 0)
            {
                ret = max(ret, 1 + tmp);
            }
        }
    }
    return ret;
}
user83834
fonte
1
encontrar todas as subsequências de X e Y em encontrar o intervalo mais longo entre elas
roquete aberração
e se eles se sobrepuserem? (as ocorrências)
user83834 10/03
1
Parece muito um dever de casa para o meu gosto dar uma solução completa. Aqui está uma dica: se você soubesse para uma determinada posição a subsequência mais longa até essa posição e a subsequência mais longa terminando nessa posição, você poderia atualizar isso para a próxima posição?
AProgrammer
@AProgrammer No próximo você quer dizer a posição i + 1?
user83834
@ratchetfreak se X fosse OPPOPPO e Y fosse OPPO, não haveria diferença. Mas a subsequência mais longa seria ignorar o O: OPPPPO do meio.
user83834

Respostas:

1

Isso deve fazer o truque. Eu escrevi em um meta-código semelhante ao básico.

LONGEST = ""
while N>0
  POS = find(T,S)
  if POS>0 then
    SUB = left(S,POS)
  else
    SUB = S
    POS = N
  endif
  if len(SUB) > len(LONGEST) then
    LONGEST = SUB
  endif
  N = N-POS
wend
burlip
fonte
0

Acho que o principal problema é o loop for dentro da instrução else, que chama a função recursivamente.

Escolha uma abordagem, recursiva ou iterada, mas misturá-las apenas parece errada.

Eu iria com a abordagem iterativa.

Eu criaria uma lista vazia fora da função.

Então ligue solve.

Nesta função, tente esta abordagem:

Repetir a sequência: se o caractere atual não for o início da subsequência, coloque o caractere em uma sequência de espera. Isso criará uma string. Se ele iniciar a subsequência, adicione esses caracteres a outra string de retenção. Marque quantas correspondências você tem contra a subsequência. Um de cada caractere, se já corresponder à subsequência, verifique se ele corresponde ao primeiro caractere e se corresponde ao caractere na próxima posição a ser correspondida. Se corresponder à subsequência, tudo o que está antes (na cadeia de espera) é colocado na lista.

Então, basicamente, você precisa rastrear o que pode ser uma sequência possível que pode vencer, e você precisa rastrear que uma subsequência possa estar dentro de outra subsequência.

Você pode precisar de várias strings de retenção, mas implemente uma abordagem simples, com duas strings de retenção, depois passe por vários exemplos e anote o que está acontecendo em cada etapa até ver se é necessário outra string de retenção.

James Black
fonte
-1

Eu acho que você precisa tratar a substring Y como uma expressão regular e transformá-la em um DFA. Em seguida, você passa a entrada pelo DFA, acompanhando quanto tempo faz desde que teve uma correspondência. Parece um problema de tempo linear, assumindo que o tamanho da entrada seja muito maior que a complexidade da string correspondente.

NovaDenizen
fonte