use clap::Parser;
use rmath::HMatrix;

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct CliArgs {
    word1: String,
    word2: String,
}

fn lcs_len(s1: &[char], s2: &[char]) -> usize {
    let m = s1.len();
    let n = s2.len();
    let mut workspace = HMatrix::<usize>::new(m, n, |(_, _)| 0);
    for i in 0..m {
        for j in 0..n {
            if s1[i] == s2[j] {
                workspace[(i, j)] = if i == 0 || j == 0 {
                    1
                } else {
                    workspace[(i - 1, j - 1)] + 1
                };
            } else {
                let left = if j > 0 { workspace[(i, j - 1)] } else { 0 };
                let up = if i > 0 { workspace[(i - 1, j)] } else { 0 };
                workspace[(i, j)] = usize::max(left, up)
            }
        }
    }
    workspace[(m - 1, n - 1)]
}

fn lcs_distance(s1: &[char], s2: &[char]) -> usize {
    let m = s1.len();
    let n = s2.len();
    let max_distance = m;
    let mut workspace = HMatrix::<usize>::new(m, n, |(_, _)| 0);
    for i in 0..m {
        for j in 0..n {
            if s1[i] == s2[j] {
                workspace[(i, j)] = if i == 0 || j == 0 {
                    max_distance - 1
                } else {
                    workspace[(i - 1, j - 1)] - 1
                };
            } else {
                let left = if j > 0 {
                    workspace[(i, j - 1)]
                } else {
                    max_distance
                };
                let up = if i > 0 {
                    workspace[(i - 1, j)]
                } else {
                    max_distance
                };
                workspace[(i, j)] = usize::min(left, up)
            }
        }
    }
    workspace[(m - 1, n - 1)]
}

fn main() {
    let args = CliArgs::parse();
    let s1 = args.word1.chars().collect::<Vec<char>>();
    let s2 = args.word2.chars().collect::<Vec<char>>();
    println!("{}", lcs_distance(&s1, &s2));
}
