Trabalho Fundamentos de Projeto e Análise de Algoritmos
Este projeto implementa uma solução completa para encontrar todas as subsequências comuns mais longas (LCS) entre duas sequências de eventos, utilizando as técnicas de Programação Dinâmica e Backtracking.
- Vue 3 + TypeScript + Vite
- Tailwind CSS para estilização moderna
- Algoritmos otimizados com código altamente legível
- Interface gráfica interativa com visualização do processo algorítmico
src/
├── algorithms/
│ ├── lcs-dynamic-programming.ts # Implementação só com Programação Dinâmica
│ └── lcs-backtracking.ts # Implementação com DP + Backtracking
├── components/
│ ├── LCSAnalyzer.vue # Componente principal
│ ├── InputSection.vue # Entrada de dados
│ ├── ResultsDisplay.vue # Exibição de resultados
│ └── DPTableVisualization.vue # Visualização da tabela DP
└── App.vue # Aplicação principal
A programação dinâmica foi aplicada para resolver o problema de forma eficiente através dos seguintes passos:
-
Definição do Subproblema:
dp[i][j]representa o comprimento da LCS entre os primeirosicaracteres da primeira string e os primeirosjcaracteres da segunda string. -
Relação de Recorrência:
dp[i][j] = { 0, se i = 0 ou j = 0 dp[i-1][j-1] + 1, se string1[i-1] = string2[j-1] max(dp[i-1][j], dp[i][j-1]), caso contrário } -
Construção Bottom-up: A tabela é preenchida de forma iterativa, sempre baseando-se em subproblemas já resolvidos.
-
Resultado Final: O valor
dp[m][n](ondemensão os comprimentos das strings) contém o comprimento da LCS.
O backtracking é necessário porque:
-
Programação Dinâmica Sozinha: Encontra apenas o comprimento da LCS, não as subsequências em si.
-
Múltiplas Soluções Ótimas: Podem existir várias LCS diferentes com o mesmo comprimento máximo. O problema pede todas as LCS, não apenas uma.
-
Reconstrução Completa: O backtracking percorre a tabela DP de forma recursiva, explorando todos os caminhos possíveis que levam ao valor ótimo.
-
Exploração Sistemática: Quando
dp[i-1][j] = dp[i][j-1] = dp[i][j], ambos os caminhos devem ser explorados, pois ambos podem levar a LCS válidas diferentes.
Principais Desafios:
-
Evitar Duplicatas: Durante o backtracking, o mesmo caminho pode ser encontrado múltiplas vezes.
- Solução: Uso de
Set<string>para armazenar apenas LCS únicas.
- Solução: Uso de
-
Complexidade Exponencial: O backtracking pode gerar muitas combinações.
- Solução: Implementação eficiente que explora apenas caminhos válidos baseados na tabela DP.
-
Ordenação Alfabética: O problema exige que as LCS sejam apresentadas em ordem alfabética.
- Solução: Conversão do Set para Array e aplicação de
.sort().
- Solução: Conversão do Set para Array e aplicação de
-
Interface Responsiva: Criar uma visualização clara para tabelas grandes.
- Solução: Componente com scroll, zoom e controles interativos.
-
Legibilidade do Código: Manter o código compreensível mesmo com lógica complexa.
- Solução: Documentação extensiva, funções bem nomeadas e separação de responsabilidades.
Complexidade de Tempo: O(m × n)
- Onde
mé o comprimento da primeira string enda segunda string - Cada célula da tabela DP é preenchida exatamente uma vez
- Cada preenchimento envolve operações O(1)
Complexidade de Espaço: O(m × n)
- Armazenamento da tabela DP de dimensões
(m+1) × (n+1)
Cálculo passo a passo:
Para strings de tamanho m e n:
- Criação da tabela: O(m × n)
- Preenchimento: O(m × n) operações
- Reconstrução de uma LCS: O(m + n)
- Total: O(m × n)
Complexidade de Tempo: O(m × n + S × L)
O(m × n): Construção da tabela DPS: Número de subsequências LCS únicasL: Comprimento médio das LCS (no máximomin(m, n))- No pior caso:
O(m × n × 2^min(m,n))quando há muitas LCS
Complexidade de Espaço: O(m × n + S × L)
O(m × n): Tabela DPO(S × L): Armazenamento de todas as LCS
Cálculo passo a passo:
1. Construção da tabela DP: O(m × n)
2. Backtracking:
- Cada célula pode gerar até 2 caminhos recursivos
- Profundidade máxima: min(m, n)
- Pior caso: O(2^min(m,n))
3. Armazenamento das LCS: O(S × L)
4. Ordenação final: O(S × L × log(S))
Exemplo Prático (com strings do roteiro):
- Helena: "ijkijkii" (8 caracteres)
- Marcus: "ikjikji" (7 caracteres)
- DP: 8 × 7 = 56 operações
- Backtracking: 7 LCS encontradas, cada uma com 5 caracteres
- Total: ~100 operações
Aprendizados Técnicos:
-
Programação Dinâmica: Compreensão profunda de como quebrar problemas complexos em subproblemas menores e reutilizar soluções.
-
Backtracking: Técnica poderosa para explorar sistematicamente todas as soluções possíveis.
-
Análise de Complexidade: Importância de entender as implicações de performance de diferentes abordagens.
-
Estruturas de Dados: Uso eficiente de Sets para evitar duplicatas e Arrays para ordenação.
Aprendizados de Engenharia de Software:
-
Código Legível: A importância de escrever código que outros desenvolvedores possam entender facilmente.
-
Separação de Responsabilidades: Dividir a lógica em módulos bem definidos (algoritmos, interface, visualização).
-
Documentação: Comentários detalhados são essenciais para explicar algoritmos complexos.
-
Testes e Validação: Implementação de funções para validar se as LCS encontradas são realmente válidas.
Aprendizados de Interface e Experiência do Usuário:
-
Visualização de Algoritmos: Como tornar conceitos abstratos visualmente compreensíveis.
-
Design Responsivo: Criar interfaces que funcionam bem em diferentes tamanhos de tela.
-
Feedback Interativo: Importância de fornecer feedback imediato ao usuário.
Aprendizados sobre Resolução de Problemas:
-
Abordagem Incremental: Resolver primeiro o problema básico (DP), depois estender para o problema completo (DP + Backtracking).
-
Otimização Prematura: Foco inicial na correção e clareza, otimização depois.
-
Casos Extremos: Considerar situações como strings vazias, caracteres repetidos, etc.
-
Instalar dependências:
npm install
-
Executar em modo de desenvolvimento:
npm run dev
-
Build para produção:
npm run build
-
Verificar tipos TypeScript:
vue-tsc -b
✅ Algoritmo de Programação Dinâmica para calcular comprimento da LCS
✅ Algoritmo de Backtracking para encontrar todas as LCS
✅ Interface gráfica moderna com Vue 3 + TypeScript
✅ Visualização interativa da tabela de programação dinâmica
✅ Validação de entradas em tempo real
✅ Exportação de resultados em formato JSON
✅ Análise de complexidade e comparação de performance
✅ Código altamente legível e bem documentado
✅ Responsividade para diferentes tamanhos de tela
src/algorithms/lcs-dynamic-programming.ts- Implementação apenas com Programação Dinâmicasrc/algorithms/lcs-backtracking.ts- Implementação com Programação Dinâmica + BacktrackingREADME.md- Este arquivo com descrição e respostas às perguntas