# Longest Valid Parentheses - C++ Solution

A comprehensive C++ implementation of the "Longest Valid Parentheses" problem with multiple algorithmic approaches.

## Problem Description

Given a string containing just the characters `'('` and `')'`, find the length of the longest valid (well-formed) parentheses substring.

### Examples

- Input: `"(()"` → Output: `2` (The longest valid parentheses substring is `"()"`)
- Input: `")()())"` → Output: `4` (The longest valid parentheses substring is `"()()"`)
- Input: `""` → Output: `0` (Empty string)

## Solution Approaches

This implementation provides three different algorithms, each with different time and space complexity trade-offs:

### 1. Dynamic Programming Approach
- **Time Complexity**: O(n)
- **Space Complexity**: O(n)
- **Method**: `FindLongestValidDp()`
- **Description**: Uses a DP array where `dp[i]` represents the length of the longest valid parentheses ending at index `i`.

### 2. Stack-Based Approach
- **Time Complexity**: O(n)
- **Space Complexity**: O(n)
- **Method**: `FindLongestValidStack()`
- **Description**: Uses a stack to track indices and calculate lengths of valid parentheses sequences.

### 3. Two-Pass Counting Approach (Space Optimized)
- **Time Complexity**: O(n)
- **Space Complexity**: O(1)
- **Method**: `FindLongestValidTwoPass()`
- **Description**: Makes two passes through the string (left-to-right and right-to-left) counting parentheses.

## Files Structure

```
├── LongestValidParentheses.h              # Header file with class declaration
├── LongestValidParentheses.cc             # Implementation file
├── test_longest_valid_parentheses.cc      # Comprehensive test suite
├── Makefile_longest_parentheses           # Build configuration
└── README_LongestValidParentheses.md      # This documentation
```

## Building and Running

### Prerequisites
- C++17 compatible compiler (g++, clang++)
- Make utility

### Quick Start

```bash
# Build the program
make -f Makefile_longest_parentheses

# Run the program with interactive demo
make -f Makefile_longest_parentheses run

# Run automated tests only
make -f Makefile_longest_parentheses test
```

### Build Options

```bash
# Debug build with sanitizers
make -f Makefile_longest_parentheses debug

# Optimized release build
make -f Makefile_longest_parentheses release

# Clean build artifacts
make -f Makefile_longest_parentheses clean

# Static analysis (requires cppcheck)
make -f Makefile_longest_parentheses analyze

# Code formatting (requires clang-format)
make -f Makefile_longest_parentheses format
```

## Usage Examples

### Basic Usage

```cpp
#include "LongestValidParentheses.h"

LongestValidParentheses solver;

// Using the default (most space-efficient) algorithm
int result = solver.FindLongestValid("()(()")  // Returns: 2

// Using specific algorithms
int dp_result = solver.FindLongestValidDp("()(()")        // Returns: 2
int stack_result = solver.FindLongestValidStack("()(()")  // Returns: 2
int two_pass_result = solver.FindLongestValidTwoPass("()(()")  // Returns: 2
```

### Test Cases Included

The test suite includes comprehensive test cases:

- Empty strings and edge cases
- Simple valid/invalid combinations
- Nested parentheses structures
- Complex mixed scenarios
- Large input performance testing

## Algorithm Details

### Dynamic Programming Algorithm

The DP approach maintains an array where `dp[i]` represents the length of the longest valid parentheses substring ending at position `i`.

**Key insights:**
- If `s[i] == ')'` and `s[i-1] == '('`: `dp[i] = dp[i-2] + 2`
- If `s[i] == ')'` and `s[i-1] == ')'`: Check for matching opening bracket

### Stack-Based Algorithm

Uses a stack to track indices of unmatched parentheses, enabling efficient calculation of valid substring lengths.

**Key insights:**
- Push indices of `'('` characters
- For `')'` characters, pop and calculate current valid length
- Maintain base index for length calculations

### Two-Pass Counting Algorithm

Makes two passes through the string with different counting strategies to handle all edge cases.

**Key insights:**
- Left-to-right pass: Reset when right count exceeds left count
- Right-to-left pass: Reset when left count exceeds right count
- Combines results from both passes for optimal solution

## Performance Characteristics

| Algorithm | Time | Space | Best Use Case |
|-----------|------|-------|---------------|
| Dynamic Programming | O(n) | O(n) | When you need to track intermediate results |
| Stack-Based | O(n) | O(n) | When you need to understand the matching process |
| Two-Pass Counting | O(n) | O(1) | When memory is constrained |

## Code Style and Standards

This implementation follows comprehensive C++ coding standards:

- **Naming Conventions**: PascalCase for classes/methods, camelCase for parameters, snake_case for local variables
- **Memory Management**: RAII principles, smart pointers where appropriate
- **Error Handling**: Input validation and graceful error handling
- **Documentation**: Comprehensive inline documentation and comments
- **Testing**: Extensive test coverage with multiple test scenarios

## Contributing

When contributing to this codebase:

1. Follow the established C++ coding standards
2. Add comprehensive tests for new functionality
3. Update documentation for any API changes
4. Ensure all existing tests pass
5. Run static analysis and address any issues

## License

This project is licensed under the Apache License 2.0. See the license headers in individual files for details.

## Algorithm Complexity Summary

All three algorithms achieve optimal O(n) time complexity, making them suitable for large inputs. The choice between them depends on your specific requirements:

- **Memory-constrained environments**: Use Two-Pass Counting
- **Need for debugging/understanding**: Use Stack-Based approach  
- **General purpose**: Use Dynamic Programming (good balance of clarity and efficiency)

The default `FindLongestValid()` method uses the Two-Pass approach for optimal space efficiency.