fix: updated LCS problem stament and tutorial

This commit is contained in:
2025-12-09 22:23:28 -03:00
parent 0951a11635
commit efbebaf61e
9 changed files with 112 additions and 16 deletions

View File

@@ -64,4 +64,49 @@ dp[0][j] = 0 \quad \forall j \ge 0
dp[i][0] = 0 \quad \forall i \ge 0
\]
Isto representa que, se uma das strings tiver tamanho zero, nenhuma subsequência comum pode ser formada.\end{document}
Isto representa que, se uma das strings tiver tamanho zero, nenhuma subsequência comum pode ser formada.
\subsection{Recuperação da Subsequência Comum}
Após o preenchimento da matriz \( dp \), o valor \( dp[n][m] \) fornece o comprimento da maior subsequência comum entre \( s_1 \) e \( s_2 \).
No entanto, para obter também a subsequência em si, é necessário realizar um processo de \textit{backtracking} sobre a matriz.
A ideia consiste em iniciar a partir da posição \( (n, m) \) da matriz e caminhar em direção à origem.
Em cada passo:
\begin{itemize}
\item Se \( s_1[i] = s_2[j] \), então este caractere faz parte da LCS. Nesse caso, retrocedemos para \( (i-1, j-1) \).
\item Caso contrário, avançamos para o vizinho que contém o maior valor entre \( dp[i-1][j] \) e \( dp[i][j-1] \), pois esse vizinho indica o caminho que manteve o comprimento máximo da subsequência.
\end{itemize}
Como a subsequência é reconstruída de trás para frente, os caracteres encontrados devem ser adicionados no início da string resultante.
O algoritmo para recuperar uma subsequência comum de comprimento máximo é o seguinte:
\begin{verbatim}
int i = n; // ponteiro para s1
int j = m; // ponteiro para s2
string lcs = ""; // subsequência comum sendo reconstruída
// Enquanto ainda houver caracteres a considerar
while (i > 0 && j > 0) {
// Caso 1: os caracteres são iguais → fazem parte da LCS
if (s1[i - 1] == s2[j - 1]) {
lcs = s1[i - 1] + lcs; // adiciona no início da string
i--;
j--;
}
// Caso 2: se o valor de cima é maior, movemos para cima
else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
}
// Caso 3: caso contrário, movemos para a esquerda
else {
j--;
}
}
\end{verbatim}
Ao final desse processo, a string \texttt{lcs} conterá uma maior subsequência comum entre as duas strings.\end{document}

View File

@@ -3,18 +3,21 @@
\begin{document}
\begin{ProblemaAutor}{}{Maior Subsequência Comum}{1}{256}{}
O problema consiste em determinar o comprimento da maior subsequência comum entre duas strings.
Uma subsequência é uma sequência que pode ser obtida a partir da string original removendo-se zero ou mais caracteres, sem alterar a ordem relativa dos restantes.
Dadas duas strings \( s_1 \) e \( s_2 \), o objetivo é encontrar o tamanho da maior subsequência que aparece em ambas.
O objetivo deste problema é determinar o comprimento da \textbf{maior subsequência comum} (Longest Common Subsequence - LCS) entre duas strings fornecidas.
Uma \textit{subsequência} é uma sequência que pode ser obtida a partir de uma string original removendo-se zero ou mais caracteres, sem alterar a ordem relativa dos caracteres restantes.
Dadas duas strings \( s_1 \) e \( s_2 \), deseja-se determinar \textbf{o comprimento da maior subsequência comum} e também \textbf{uma subsequência comum de comprimento máximo} presente em ambas.
\Entrada
A entrada é composta por duas linhas. Na primeira linha, há dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 1000 \)), representando respectivamente os tamanhos das strings \( s_1 \) e \( s_2 \).
A entrada é composta por duas linhas.
Na primeira linha, há dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 1000 \)), representando respectivamente os tamanhos das strings \( s_1 \) e \( s_2 \).
Na segunda linha, há duas strings \( s_1 \) e \( s_2 \), cada uma composta apenas por letras minúsculas do alfabeto, com tamanhos \( n \) e \( m \), respectivamente.
\Saida
Imprima um único inteiro representando o comprimento da maior subsequência comum entre \( s_1 \) e \( s_2 \).
A saída consiste em duas linhas.
Na primeira linha, deve ser impresso o comprimento da maior subsequência comum.
Na segunda linha, deve ser impressa uma subsequência comum de comprimento máximo.
\ExemploEntrada
\begin{Exemplo}
@@ -32,8 +35,8 @@ Imprima um único inteiro representando o comprimento da maior subsequência com
Para as strings \( s_1 = abcde \) e \( s_2 = ace \), a maior subsequência comum é "ace", que possui tamanho 3.
Para \( s_1 = abc \) e \( s_2 = abc \), ambas as strings são idênticas, então a maior subsequência comum tem tamanho 3.
Para \( s_1 = abc \) e \( s_2 = abc \), ambas as strings são idênticas, logo a maior subsequência comum é "abc", que possui tamanho 3.
Para \( s_1 = abc \) e \( s_2 = hhh \), não há caracteres em comum, e portanto a maior subsequência comum tem tamanho 0.
Para \( s_1 = abc \) e \( s_2 = hhh \), não há caracteres em comum, e portanto a maior subsequência comum é a palavra vazia, que tem tamanho 0.
\end{ProblemaAutor}
\end{document}

View File

@@ -1,3 +1,3 @@
O problema consiste em determinar o comprimento da maior subsequência comum entre duas strings.
Uma subsequência é uma sequência que pode ser obtida a partir da string original removendo-se zero ou mais caracteres, sem alterar a ordem relativa dos restantes.
Dadas duas strings \( s_1 \) e \( s_2 \), o objetivo é encontrar o tamanho da maior subsequência que aparece em ambas.
O objetivo deste problema é determinar o comprimento da \textbf{maior subsequência comum} (Longest Common Subsequence - LCS) entre duas strings fornecidas.
Uma \textit{subsequência} é uma sequência que pode ser obtida a partir de uma string original removendo-se zero ou mais caracteres, sem alterar a ordem relativa dos caracteres restantes.
Dadas duas strings \( s_1 \) e \( s_2 \), deseja-se determinar \textbf{o comprimento da maior subsequência comum} e também \textbf{uma subsequência comum de comprimento máximo} presente em ambas.

View File

@@ -1,2 +1,3 @@
A entrada é composta por duas linhas. Na primeira linha, há dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 1000 \)), representando respectivamente os tamanhos das strings \( s_1 \) e \( s_2 \).
A entrada é composta por duas linhas.
Na primeira linha, há dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 1000 \)), representando respectivamente os tamanhos das strings \( s_1 \) e \( s_2 \).
Na segunda linha, há duas strings \( s_1 \) e \( s_2 \), cada uma composta apenas por letras minúsculas do alfabeto, com tamanhos \( n \) e \( m \), respectivamente.

View File

@@ -1,5 +1,5 @@
Para as strings \( s_1 = abcde \) e \( s_2 = ace \), a maior subsequência comum é "ace", que possui tamanho 3.
Para \( s_1 = abc \) e \( s_2 = abc \), ambas as strings são idênticas, então a maior subsequência comum tem tamanho 3.
Para \( s_1 = abc \) e \( s_2 = abc \), ambas as strings são idênticas, logo a maior subsequência comum é "abc", que possui tamanho 3.
Para \( s_1 = abc \) e \( s_2 = hhh \), não há caracteres em comum, e portanto a maior subsequência comum tem tamanho 0.
Para \( s_1 = abc \) e \( s_2 = hhh \), não há caracteres em comum, e portanto a maior subsequência comum é a palavra vazia, que tem tamanho 0.

View File

@@ -1 +1,3 @@
Imprima um único inteiro representando o comprimento da maior subsequência comum entre \( s_1 \) e \( s_2 \).
A saída consiste em duas linhas.
Na primeira linha, deve ser impresso o comprimento da maior subsequência comum.
Na segunda linha, deve ser impressa uma subsequência comum de comprimento máximo.

View File

@@ -52,3 +52,48 @@ dp[i][0] = 0 \quad \forall i \ge 0
\]
Isto representa que, se uma das strings tiver tamanho zero, nenhuma subsequência comum pode ser formada.
\subsection{Recuperação da Subsequência Comum}
Após o preenchimento da matriz \( dp \), o valor \( dp[n][m] \) fornece o comprimento da maior subsequência comum entre \( s_1 \) e \( s_2 \).
No entanto, para obter também a subsequência em si, é necessário realizar um processo de \textit{backtracking} sobre a matriz.
A ideia consiste em iniciar a partir da posição \( (n, m) \) da matriz e caminhar em direção à origem.
Em cada passo:
\begin{itemize}
\item Se \( s_1[i] = s_2[j] \), então este caractere faz parte da LCS. Nesse caso, retrocedemos para \( (i-1, j-1) \).
\item Caso contrário, avançamos para o vizinho que contém o maior valor entre \( dp[i-1][j] \) e \( dp[i][j-1] \), pois esse vizinho indica o caminho que manteve o comprimento máximo da subsequência.
\end{itemize}
Como a subsequência é reconstruída de trás para frente, os caracteres encontrados devem ser adicionados no início da string resultante.
O algoritmo para recuperar uma subsequência comum de comprimento máximo é o seguinte:
\begin{verbatim}
int i = n; // ponteiro para s1
int j = m; // ponteiro para s2
string lcs = ""; // subsequência comum sendo reconstruída
// Enquanto ainda houver caracteres a considerar
while (i > 0 && j > 0) {
// Caso 1: os caracteres são iguais → fazem parte da LCS
if (s1[i - 1] == s2[j - 1]) {
lcs = s1[i - 1] + lcs; // adiciona no início da string
i--;
j--;
}
// Caso 2: se o valor de cima é maior, movemos para cima
else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
}
// Caso 3: caso contrário, movemos para a esquerda
else {
j--;
}
}
\end{verbatim}
Ao final desse processo, a string \texttt{lcs} conterá uma maior subsequência comum entre as duas strings.