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 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{document}
\begin{ProblemaAutor}{}{Maior Subsequência Comum}{1}{256}{} \begin{ProblemaAutor}{}{Maior Subsequência Comum}{1}{256}{}
O problema consiste em determinar o comprimento da maior subsequência comum entre duas strings. O objetivo deste problema é determinar o comprimento da \textbf{maior subsequência comum} (Longest Common Subsequence - LCS) entre duas strings fornecidas.
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. 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 \), o objetivo é encontrar o tamanho da maior subsequência que aparece em ambas. 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 \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. 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 \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 \ExemploEntrada
\begin{Exemplo} \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 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{ProblemaAutor}
\end{document} \end{document}

View File

@@ -1,3 +1,3 @@
O problema consiste em determinar o comprimento da maior subsequência comum entre duas strings. O objetivo deste problema é determinar o comprimento da \textbf{maior subsequência comum} (Longest Common Subsequence - LCS) entre duas strings fornecidas.
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. 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 \), o objetivo é encontrar o tamanho da maior subsequência que aparece em ambas. 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. 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 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. 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.