Problem: 2050E - Three Strings
Language: C++17 (GCC 7-32)

Previous submission (verdict: Time limit exceeded on test 16):
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define int long long
#define pb push_back
#define f(i, s, n) for (int i = s; i < n; i++)
#define fr(i, n, s) for (int i = n; i >= s; i--)
#define fa(ele, vec) for (auto ele : vec)
#define pii pair<int, int>
#define pyes cout << "YES"
#define pno cout << "NO"
#define all(arr) arr.begin(), arr.end()
#define vi vector<int>
#define vvi vector<vector<int>>
#define vs vector<string>
#define vvs vector<vector<string>>
#define vc vector<char>

class Trie
{
    vector<vector<int>> trie_node;
    vector<int> end_node;
    int counter;

    public:

        Trie(int total_node)
        {
            counter = 0;
            for(int i=0; i<total_node; i++)
            {
                vector<int> char_node((int)26, 0);
                trie_node.push_back(char_node);
                end_node.push_back(0);
            }
        }
        void insert(string word)
        {
            int curr = 0;
            for(char character: word)
            {
                if(trie_node[curr][character-'a'] == 0)
                {
                    trie_node[curr][character-'a'] = ++counter;
                }
                curr = trie_node[curr][character-'a'];

            }
            end_node[curr] = 1;
        }

};

void sort_two_array(vi &arr1, vi &arr2, bool descending = 0)
{
    int n = arr1.size();
    vi indices(n);
    for (int i = 0; i < n; ++i)
    {
        indices[i] = i;
    }

    if (descending == 0)
    {
        sort(indices.begin(), indices.end(), [&](int a, int b)
             { return arr1[a] < arr1[b]; });
    }
    else
    {
        sort(indices.begin(), indices.end(), [&](int a, int b)
             { return arr1[a] > arr1[b]; });
    }

    if (descending == 0)
    {
        sort(arr1.begin(), arr1.end());
    }
    else
    {
        sort(arr1.begin(), arr1.end());
        reverse(arr1.begin(), arr1.end());
    }
    vi temp(n);
    f(i, 0, n)
    {
        temp[i] = arr2[indices[i]];
    }
    f(i, 0, n)
    {
        arr2[i] = temp[i];
    }
}

int sumofdigits(int x)
{
    int temp = x;
    int sum = 0;
    while (temp != 0)
    {
        sum += temp % 10;
        temp = temp / 10;
    }
    return sum;
}

int custompow(int m, int n)
{
    int ans = 1;
    f(i, 1, n + 1)
    {
        ans = ans * m;
    }
    return ans;
}

int powerof2(int n)
{
    f(i, 1, n + 1)
    {
        if (pow(2, i) > n)
        {
            return i - 1;
        }
    }
    return 0;
}

int gcd(int a, int b)
{
    while (b != 0)
    {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

// Function to calculate the HCF of an array of numbers
int findHCF(vi arr, int n)
{
    int hcf = arr[0];

    for (int i = 1; i < n; ++i)
    {
        hcf = gcd(hcf, arr[i]);
    }

    return hcf;
}

int binarysearch(vi arr, int num)
{
    int n = arr.size();
    int s = 0, e = n - 1;
    while (s <= e)
    {
        int mid = (s + e) / 2;
        if (mid == s)
        {
            break;
        }
        if (arr[mid] == num)
        {
            return mid;
        }
        else if (arr[mid] > num)
        {
            e = mid;
        }
        else
            s = mid;
    }
    if (num >= arr[e])
    {
        return e;
    }
    else if (num <= arr[s])
    {
        return s;
    }
    else
    {
        if ((num - arr[s]) <= (arr[e] - num))
        {
            return s;
        }
        else
            return e;
    }
    return -1;
}

string intToBinary(int number, int numBits)
{
    return std::bitset<sizeof(int) * 8>(number).to_string().substr(sizeof(int) * 8 - numBits);
}

int binaryToInt(string binaryString)
{
    int ans = 0;
    int n = binaryString.size();
    f(i, 0, n)
    {
        if (binaryString[i] == '1')
        {
            ans = ans + custompow(2, n - i - 1);
        }
    }
    return ans;
}

vector<string> all_binary_subseq(int n)
{
    vector<string> ans;
    f(i, 0, custompow(2, n))
    {
        ans.push_back(intToBinary(i, n));
    }
    return ans;
}

vi findDivisors(int num)
{
    vi divisors;

    for (int i = 1; i * i <= num; ++i)
    {
        if (num % i == 0)
        {
            divisors.push_back(i);

            // If the divisor is not equal to the square root, add the corresponding divisor
            if (i != num / i)
            {
                divisors.push_back(num / i);
            }
        }
    }

    return divisors;
}

string XOR(string a, string b)
{
    string ans = "";
    f(i, 0, a.size())
    {
        if (a[i] == b[i])
            ans.push_back('0');
        else
            ans.push_back('1');
    }
    return ans;
}

int sum_of_vector(vi &arr)
{
    int sum = 0;
    for (auto a : arr)
    {
        sum += a;
    }
    return sum;
}

void take_vec_input(vi &arr)
{
    int n = arr.size();
    f(i, 0, n) cin >> arr[i];
}
void give_vec_output(vi arr)
{
    int n = arr.size();
    f(i, 0, n) cout << arr[i] << " ";
}

int find_max(vi &a)
{
    int ans = a[0];
    f(i, 1, a.size())
    {
        ans = max(ans, a[i]);
    }
    return ans;
}

int KMP(string a, string b)
{
    if(a == "" || b == "")return 0;
    vi lsp(b.size(), 0);
    int k = 1;
    f(i, 0, b.size())
    {
        if(k-1 != i && b[k-1] == b[i])
        {
            lsp[i] = k;
            k++;
        }
        else k = 1;
    }
    k = -1;
    int i;
    bool flag = 0;
    for(i=0; i < a.size(); i++)
    {
        if(a[i] == b[k+1] || a[i] == '?')
        {
            k++;
            if(k+1 == b.size())
            {
                flag = 1;
                break;
            }
        }
        else
        {
            
            if(k != -1)
            {
                k--;
                k = lsp[k]-1;
                i--;
            }
        }
    }
    if(flag == 1)
    {
        return i-k;
    }
    return -1;

}

int ncr(int n, int r)
{
    if(n < r)return 0;
    int ans = 1;
    for(int i=1; i<=r; i++)
    {
        ans *= ((n-r+i)/i);
        ans = ans%mod;
    }
    return ans;
}

int ask(int u, int v)
{
	cout << "? " << u << " " << v << endl;
	int ans;
	cin >> ans;
	return ans;
}

int calculatepossiblity(vi k, int num)
{
    int ans = 0;
    f(i, 0, k.size())
    {
        ans += (num/k[i]);
        if (ans >= INT32_MAX)return INT64_MAX;
    }
    return ans;
}

// Famous approach of binary seach through whole case
int binsearch_solution(int n, int t, vi k)
{
    int left = 0, right = custompow(10, 18);
    while (left < right)
    {
        if(left+1 == right)break;
        int mid = (left + right)/2;
        int ans = calculatepossiblity(k, mid);
        if(t > ans)
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
        
    }
    if(calculatepossiblity(k, left) >= t)return left;
    return right;
    
}

/*
   lower_bound(A.begin(), A.end(), num) - A.begin() will return first index in A where num should be kept so that no change in order
   upper_bound(A.begin(), A.end(), num) - A.begin() will return index such that num will be kept there and all the number right of num must be strictly greater than num
   3 << 4 --> left shift of all (important) the bits of 3 by 4 position
   3 >> 4 --> right shift of all (important) the bits of 3 by 4 position (eg 10 >> 4 == 0)
*/

//----------------------------------------------------------------------------

int recursion(string a, string b, string c, int i, int j, int k, vvi &dp)
{
    if(dp[i][j] != -1)return dp[i][j];
    if(i >= a.size())
    {
        int ans = 0;
        for(int m = 0; m < b.size()-j; m++)
        {
            if(b[j+m] != c[k+m])ans++;
        }
        return ans;
    }
    else if(j >= b.size())
    {
        int ans = 0;
        for(int m = 0; m < a.size()-i; m++)
        {
            if(a[i+m] != c[k+m])ans++;
        }
        return ans;
    }
    

    int ans_a_remove;
    if(dp[i+1][j] == -1)
    {
        ans_a_remove = recursion(a, b, c, i+1, j, k+1, dp);
        dp[i+1][j] = ans_a_remove;
    }
    else ans_a_remove = dp[i+1][j];
    if(a[i] != c[k])ans_a_remove++;

    int ans_b_remove;
    if(dp[i][j+1] == -1)
    {
        ans_b_remove = recursion(a, b, c, i, j+1, k+1, dp);
        dp[i][j+1] = ans_b_remove;
    }
    else ans_b_remove = dp[i][j+1];
    if (b[j] != c[k])ans_b_remove++;

    dp[i][j] = min(ans_a_remove, ans_b_remove);
    return dp[i][j];

}

void solve()
{
    string a, b, c;
    cin>>a>>b>>c;
    vvi dp(a.size()+1, vi(b.size()+1, -1));
    int nequal = 0;
    fr(i, a.size()-1, 0)
    {
        if(a[i] != c[b.size()+i])nequal++;
        dp[i][b.size()] = nequal;
    }
    nequal = 0;
    fr(i, b.size()-1, 0)
    {
        if(b[i] != c[a.size()+i])nequal++;
        dp[a.size()][i] = nequal;
    }
    dp[a.size()][b.size()] = 0;
    cout<<recursion(a, b, c, 0, 0, 0, dp);



}

//---------------------------------------------------------------------------------

signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
        cout << endl;
    }

    return 0;
}

Submission (verdict: Accepted):
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define int long long
#define pb push_back
#define f(i, s, n) for (int i = s; i < n; i++)
#define fr(i, n, s) for (int i = n; i >= s; i--)
#define fa(ele, vec) for (auto ele : vec)
#define pii pair<int, int>
#define pyes cout << "YES"
#define pno cout << "NO"
#define all(arr) arr.begin(), arr.end()
#define vi vector<int>
#define vvi vector<vector<int>>
#define vs vector<string>
#define vvs vector<vector<string>>
#define vc vector<char>

class Trie
{
    vector<vector<int>> trie_node;
    vector<int> end_node;
    int counter;

    public:

        Trie(int total_node)
        {
            counter = 0;
            for(int i=0; i<total_node; i++)
            {
                vector<int> char_node((int)26, 0);
                trie_node.push_back(char_node);
                end_node.push_back(0);
            }
        }
        void insert(string word)
        {
            int curr = 0;
            for(char character: word)
            {
                if(trie_node[curr][character-'a'] == 0)
                {
                    trie_node[curr][character-'a'] = ++counter;
                }
                curr = trie_node[curr][character-'a'];

            }
            end_node[curr] = 1;
        }

};

void sort_two_array(vi &arr1, vi &arr2, bool descending = 0)
{
    int n = arr1.size();
    vi indices(n);
    for (int i = 0; i < n; ++i)
    {
        indices[i] = i;
    }

    if (descending == 0)
    {
        sort(indices.begin(), indices.end(), [&](int a, int b)
             { return arr1[a] < arr1[b]; });
    }
    else
    {
        sort(indices.begin(), indices.end(), [&](int a, int b)
             { return arr1[a] > arr1[b]; });
    }

    if (descending == 0)
    {
        sort(arr1.begin(), arr1.end());
    }
    else
    {
        sort(arr1.begin(), arr1.end());
        reverse(arr1.begin(), arr1.end());
    }
    vi temp(n);
    f(i, 0, n)
    {
        temp[i] = arr2[indices[i]];
    }
    f(i, 0, n)
    {
        arr2[i] = temp[i];
    }
}

int sumofdigits(int x)
{
    int temp = x;
    int sum = 0;
    while (temp != 0)
    {
        sum += temp % 10;
        temp = temp / 10;
    }
    return sum;
}

int custompow(int m, int n)
{
    int ans = 1;
    f(i, 1, n + 1)
    {
        ans = ans * m;
    }
    return ans;
}

int powerof2(int n)
{
    f(i, 1, n + 1)
    {
        if (pow(2, i) > n)
        {
            return i - 1;
        }
    }
    return 0;
}

int gcd(int a, int b)
{
    while (b != 0)
    {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

// Function to calculate the HCF of an array of numbers
int findHCF(vi arr, int n)
{
    int hcf = arr[0];

    for (int i = 1; i < n; ++i)
    {
        hcf = gcd(hcf, arr[i]);
    }

    return hcf;
}

int binarysearch(vi arr, int num)
{
    int n = arr.size();
    int s = 0, e = n - 1;
    while (s <= e)
    {
        int mid = (s + e) / 2;
        if (mid == s)
        {
            break;
        }
        if (arr[mid] == num)
        {
            return mid;
        }
        else if (arr[mid] > num)
        {
            e = mid;
        }
        else
            s = mid;
    }
    if (num >= arr[e])
    {
        return e;
    }
    else if (num <= arr[s])
    {
        return s;
    }
    else
    {
        if ((num - arr[s]) <= (arr[e] - num))
        {
            return s;
        }
        else
            return e;
    }
    return -1;
}

string intToBinary(int number, int numBits)
{
    return std::bitset<sizeof(int) * 8>(number).to_string().substr(sizeof(int) * 8 - numBits);
}

int binaryToInt(string binaryString)
{
    int ans = 0;
    int n = binaryString.size();
    f(i, 0, n)
    {
        if (binaryString[i] == '1')
        {
            ans = ans + custompow(2, n - i - 1);
        }
    }
    return ans;
}

vector<string> all_binary_subseq(int n)
{
    vector<string> ans;
    f(i, 0, custompow(2, n))
    {
        ans.push_back(intToBinary(i, n));
    }
    return ans;
}

vi findDivisors(int num)
{
    vi divisors;

    for (int i = 1; i * i <= num; ++i)
    {
        if (num % i == 0)
        {
            divisors.push_back(i);

            // If the divisor is not equal to the square root, add the corresponding divisor
            if (i != num / i)
            {
                divisors.push_back(num / i);
            }
        }
    }

    return divisors;
}

string XOR(string a, string b)
{
    string ans = "";
    f(i, 0, a.size())
    {
        if (a[i] == b[i])
            ans.push_back('0');
        else
            ans.push_back('1');
    }
    return ans;
}

int sum_of_vector(vi &arr)
{
    int sum = 0;
    for (auto a : arr)
    {
        sum += a;
    }
    return sum;
}

void take_vec_input(vi &arr)
{
    int n = arr.size();
    f(i, 0, n) cin >> arr[i];
}
void give_vec_output(vi arr)
{
    int n = arr.size();
    f(i, 0, n) cout << arr[i] << " ";
}

int find_max(vi &a)
{
    int ans = a[0];
    f(i, 1, a.size())
    {
        ans = max(ans, a[i]);
    }
    return ans;
}

int KMP(string a, string b)
{
    if(a == "" || b == "")return 0;
    vi lsp(b.size(), 0);
    int k = 1;
    f(i, 0, b.size())
    {
        if(k-1 != i && b[k-1] == b[i])
        {
            lsp[i] = k;
            k++;
        }
        else k = 1;
    }
    k = -1;
    int i;
    bool flag = 0;
    for(i=0; i < a.size(); i++)
    {
        if(a[i] == b[k+1] || a[i] == '?')
        {
            k++;
            if(k+1 == b.size())
            {
                flag = 1;
                break;
            }
        }
        else
        {
            
            if(k != -1)
            {
                k--;
                k = lsp[k]-1;
                i--;
            }
        }
    }
    if(flag == 1)
    {
        return i-k;
    }
    return -1;

}

int ncr(int n, int r)
{
    if(n < r)return 0;
    int ans = 1;
    for(int i=1; i<=r; i++)
    {
        ans *= ((n-r+i)/i);
        ans = ans%mod;
    }
    return ans;
}

int ask(int u, int v)
{
	cout << "? " << u << " " << v << endl;
	int ans;
	cin >> ans;
	return ans;
}

int calculatepossiblity(vi k, int num)
{
    int ans = 0;
    f(i, 0, k.size())
    {
        ans += (num/k[i]);
        if (ans >= INT32_MAX)return INT64_MAX;
    }
    return ans;
}

// Famous approach of binary seach through whole case
int binsearch_solution(int n, int t, vi k)
{
    int left = 0, right = custompow(10, 18);
    while (left < right)
    {
        if(left+1 == right)break;
        int mid = (left + right)/2;
        int ans = calculatepossiblity(k, mid);
        if(t > ans)
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
        
    }
    if(calculatepossiblity(k, left) >= t)return left;
    return right;
    
}

/*
   lower_bound(A.begin(), A.end(), num) - A.begin() will return first index in A where num should be kept so that no change in order
   upper_bound(A.begin(), A.end(), num) - A.begin() will return index such that num will be kept there and all the number right of num must be strictly greater than num
   3 << 4 --> left shift of all (important) the bits of 3 by 4 position
   3 >> 4 --> right shift of all (important) the bits of 3 by 4 position (eg 10 >> 4 == 0)
*/

//----------------------------------------------------------------------------

int recursion(string a, string b, string c, int i, int j, int k, vvi &dp)
{
    if(dp[i][j] != -1)return dp[i][j];
    if(i >= a.size())
    {
        int ans = 0;
        for(int m = 0; m < b.size()-j; m++)
        {
            if(b[j+m] != c[k+m])ans++;
        }
        return ans;
    }
    else if(j >= b.size())
    {
        int ans = 0;
        for(int m = 0; m < a.size()-i; m++)
        {
            if(a[i+m] != c[k+m])ans++;
        }
        return ans;
    }
    

    int ans_a_remove;
    if(dp[i+1][j] == -1)
    {
        ans_a_remove = recursion(a, b, c, i+1, j, k+1, dp);
        dp[i+1][j] = ans_a_remove;
    }
    else ans_a_remove = dp[i+1][j];
    if(a[i] != c[k])ans_a_remove++;

    int ans_b_remove;
    if(dp[i][j+1] == -1)
    {
        ans_b_remove = recursion(a, b, c, i, j+1, k+1, dp);
        dp[i][j+1] = ans_b_remove;
    }
    else ans_b_remove = dp[i][j+1];
    if (b[j] != c[k])ans_b_remove++;

    dp[i][j] = min(ans_a_remove, ans_b_remove);
    return dp[i][j];

}

void solve()
{
    string a, b, c;
    cin>>a>>b>>c;
    vvi dp(a.size()+1, vi(b.size()+1, -1));
    int nequal = 0;
    fr(i, a.size()-1, 0)
    {
        if(a[i] != c[b.size()+i])nequal++;
        dp[i][b.size()] = nequal;
    }
    nequal = 0;
    fr(i, b.size()-1, 0)
    {
        if(b[i] != c[a.size()+i])nequal++;
        dp[a.size()][i] = nequal;
    }
    dp[a.size()][b.size()] = 0;
    fr(i, a.size()-1, 0)
    {
        fr(j, b.size()-1, 0)
        {
            int ans_a_remove = dp[i+1][j];
            if(a[i] != c[i+j])ans_a_remove++;

            int ans_b_remove = dp[i][j+1];;
            if (b[j] != c[i+j])ans_b_remove++;

            dp[i][j] = min(ans_a_remove, ans_b_remove);
        }
    }


    cout<<dp[0][0];



}

//---------------------------------------------------------------------------------

signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
        cout << endl;
    }

    return 0;
}