Updating lazy-frog files

This commit is contained in:
2026-05-10 13:44:44 -03:00
parent 9c9bb62c23
commit 189f75019b
70 changed files with 2034 additions and 1 deletions

View File

@@ -0,0 +1,114 @@
\documentclass[10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{fullpage}
\usepackage{url}
\pagenumbering{gobble}
\usepackage{hyperref}
\usepackage{graphicx}
\input{statement/preamble.tex}
\title{ Tutorial: Maior Subsequência Comum}
\author{}
\date{}
\begin{document}
\maketitle
\section{Solução do Problema}
O problema da maior subsequência comum (\textit{Longest Common Subsequence}, LCS) pode ser resolvido por meio de \textit{programação dinâmica}.
A ideia central é decompor o problema em subproblemas menores, de forma que a solução ótima final seja construída a partir das soluções ótimas desses subproblemas.
\subsection{Definição do Subproblema}
Sejam duas strings \( s_1 \) e \( s_2 \), de tamanhos \( n \) e \( m \), respectivamente.
Definimos:
\[
dp[i][j] = \text{o comprimento da maior subsequência comum entre } s_1[1..i] \text{ e } s_2[1..j].
\]
Isto é, \( dp[i][j] \) representa a resposta do problema considerando apenas os primeiros \( i \) caracteres de \( s_1 \) e os primeiros \( j \) caracteres de \( s_2 \).
\subsection{Função de Transição}
Ao analisar um par de posições \( (i, j) \), temos duas possibilidades principais:
\begin{itemize}
\item Se os caracteres atuais são iguais, isto é, \( s_1[i] = s_2[j] \), então podemos estender uma subsequência comum encontrada anteriormente:
\[
dp[i][j] = dp[i-1][j-1] + 1.
\]
\item Caso contrário, não é possível usar ambos os caracteres ao mesmo tempo, então devemos escolher o melhor resultado entre ignorar um dos dois:
\[
dp[i][j] = \max(dp[i-1][j], \, dp[i][j-1]).
\]
\end{itemize}
Assim, a função de transição pode ser resumida como:
\[
dp[i][j] =
\begin{cases}
dp[i-1][j-1] + 1, & \text{se } s_1[i] = s_2[j] \\
\max(dp[i-1][j], \, dp[i][j-1]), & \text{caso contrário}
\end{cases}
\]
\subsection{Casos Base}
Os casos base seguem a lógica natural do problema:
\[
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.
\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

@@ -0,0 +1,43 @@
\documentclass{maratona}
\begin{document}
\begin{ProblemaAutor}{}{Maior Subsequência Comum}{1}{256}{}
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 \).
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
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}
\texttt{5~3} & \texttt{3}\\
\texttt{abcde~ace} & \texttt{ace}\\
\rowcolor{gray!20}\texttt{3~3} & \texttt{3}\\
\rowcolor{gray!20}\texttt{abc~abc} & \texttt{abc}\\
\texttt{3~3} & \texttt{0}\\
\texttt{abc~hhh} & \texttt{}\\
\end{Exemplo}
\Notas
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, 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 é a palavra vazia, que tem tamanho 0.
\end{ProblemaAutor}
\end{document}