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 = aaabc
e 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 = aaab
e 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;
}
fonte
Respostas:
Isso deve fazer o truque. Eu escrevi em um meta-código semelhante ao básico.
fonte
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.
fonte
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.
fonte