#include <algorithm>
#include <string>
#include <vector>

int edit_distance(const std::string &s1, const std::string &s2) {
    size_t m = s1.size();
    size_t n = s2.size();

    // Create a 2D DP table
    std::vector<std::vector<size_t>> dp(m + 1, std::vector<size_t>(n + 1));

    // Fill the base cases
    for (size_t i = 0; i <= m; ++i)
        dp[i][0] = i; // Deletion cost

    for (size_t j = 0; j <= n; ++j)
        dp[0][j] = j; // Insertion cost

    // Fill the DP table
    for (size_t i = 1; i <= m; ++i) {
        for (size_t j = 1; j <= n; ++j) {
            if (s1[i - 1] == s2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1]; // No operation needed
            } else {
                dp[i][j] = 1 + std::min({
                                   dp[i - 1][j],    // Deletion
                                   dp[i][j - 1],    // Insertion
                                   dp[i - 1][j - 1] // Substitution
                               });
            }
        }
    }

    return static_cast<int>(dp[m][n]);
}