Problem: 2050E - Three Strings
Language: c++20 

Code 1:
#include <bits/stdc++.h>
using namespace std;


// Credits to HealthyUG for the inspiration.
// Segment Tree with Point Updates and Range Queries
// Supports multiple Segment Trees with just a change in the Node and Update
// Very few changes required everytime

template<typename Node, typename Update>
struct SegTree {
	vector<Node> tree;
	vector<int> arr; // type may change
	int n;
	int s;
	SegTree(int a_len) { // change if type updated
		vector<int> a(a_len+5,0);
        arr=a;
		n = a_len+5;
		s = 1;
		while(s < 2 * n){
			s = s << 1;
		}
		tree.resize(s); 
        for(int i=0;i<s;i++){
            tree[i]=Node();
        }
        //fill(all(tree), Node());
		build(0, n - 1, 1);
	}
	void build(int start, int end, int index)  // Never change this
	{
		if (start == end)	{
			tree[index] = Node(arr[start]);
			return;
		}
		int mid = (start + end) / 2;
		build(start, mid, 2 * index);
		build(mid + 1, end, 2 * index + 1);
		tree[index].merge(tree[2 * index], tree[2 * index + 1]);
	}
	void update(int start, int end, int index, int query_index, Update &u)  // Never Change this
	{
		if (start == end) {
			u.apply(tree[index]);
			return;
		}
		int mid = (start + end) / 2;
		if (mid >= query_index)
			update(start, mid, 2 * index, query_index, u);
		else
			update(mid + 1, end, 2 * index + 1, query_index, u);
		tree[index].merge(tree[2 * index], tree[2 * index + 1]);
	}
	Node query(int start, int end, int index, int left, int right) { // Never change this
		if (start > right || end < left)
			return Node();
		if (start >= left && end <= right)
			return tree[index];
		int mid = (start + end) / 2;
		Node l, r, ans;
		l = query(start, mid, 2 * index, left, right);
		r = query(mid + 1, end, 2 * index + 1, left, right);
		ans.merge(l, r);
		return ans;
	}
	void make_update(int index, int val) {  // pass in as many parameters as required
		Update new_update = Update(val); // may change
		update(0, n - 1, 1, index, new_update);
	}
	Node make_query(int left, int right) {
		return query(0, n - 1, 1, left, right);
	}
};

struct Node1 {
	long long val; // may change
	Node1() { // Identity element
		val = 0;	// may change
	}
	Node1(long long p1) {  // Actual Node
		val = p1; // may change
	}
	void merge(Node1 &l, Node1 &r) { // Merge two child nodes
		val = max(l.val , r.val);  // may change
	}
};

struct Update1 {
	long long val; // may change
	Update1(long long p1) { // Actual Update
		val = p1; // may change
	}
	void apply(Node1 &a) { // apply update to given node
		a.val = max(a.val,val); // may change
	}
};





//Union Find Algorithm Almost O(1) for reasonable size N. O(log*N) to be precise
struct UnionFind {
	int n;
	vector<int> rank;
	vector<int> parent;
	// store other info as required
	UnionFind(int n) {
		rank.resize(n);
		fill(rank.begin(), rank.end(), 0);
		parent.resize(n);
		for (int i = 0; i < n; i++) {
			parent[i] = i;
		}
	}
	int get(int a) {
		return parent[a] = (parent[a] == a ? a : get(parent[a]));
	}
	void merge(int a, int b) {
		a = get(a);
		b = get(b);
		if (a == b) {
			return;
		}
		if (rank[a] == rank[b]) {
			rank[a]++;
		}
		if (rank[a] > rank[b]) {
			parent[b] = a;
		} else {
			parent[a] = b;
		}
	}
};

void ask(string s){
	cout<<1<<" "<<s<<endl;
}

int solve(string a,string b,string c,int i,int j,int n,int m,vector<vector<int>>&dp){
	if(i==n && j==m){
		return 0;
	}
	if(dp[i][j]!=-1)return dp[i][j];
	if(i==n){
		return (b[j]!=c[i+j])+solve(a,b,c,i,j+1,n,m,dp);
	}
	if(j==m){
		return (a[i]!=c[i+j])+solve(a,b,c,i+1,j,n,m,dp);
	}

	int takea=INT_MAX;
	int takeb=INT_MAX;
	takea=(a[i]!=c[i+j])+solve(a,b,c,i+1,j,n,m,dp);
	takeb=(b[j]!=c[i+j])+solve(a,b,c,i,j+1,n,m,dp);
	return dp[i][j]=min(takea,takeb);
}

signed main(){
	//  x^y = x + y - 2(x&y);
	int t;
	cin>>t;
	while(t--){
		string a,b,c;
		cin>>a>>b>>c;
		vector<vector<int>> dp(a.length()+2,vector<int>(b.length()+2,-1));
		int ans=solve(a,b,c,0,0,a.length(),b.length(),dp);
		cout<<ans<<endl;
	}
}

Code 2:
#include <bits/stdc++.h>
using namespace std;


// Credits to HealthyUG for the inspiration.
// Segment Tree with Point Updates and Range Queries
// Supports multiple Segment Trees with just a change in the Node and Update
// Very few changes required everytime

template<typename Node, typename Update>
struct SegTree {
	vector<Node> tree;
	vector<int> arr; // type may change
	int n;
	int s;
	SegTree(int a_len) { // change if type updated
		vector<int> a(a_len+5,0);
        arr=a;
		n = a_len+5;
		s = 1;
		while(s < 2 * n){
			s = s << 1;
		}
		tree.resize(s); 
        for(int i=0;i<s;i++){
            tree[i]=Node();
        }
        //fill(all(tree), Node());
		build(0, n - 1, 1);
	}
	void build(int start, int end, int index)  // Never change this
	{
		if (start == end)	{
			tree[index] = Node(arr[start]);
			return;
		}
		int mid = (start + end) / 2;
		build(start, mid, 2 * index);
		build(mid + 1, end, 2 * index + 1);
		tree[index].merge(tree[2 * index], tree[2 * index + 1]);
	}
	void update(int start, int end, int index, int query_index, Update &u)  // Never Change this
	{
		if (start == end) {
			u.apply(tree[index]);
			return;
		}
		int mid = (start + end) / 2;
		if (mid >= query_index)
			update(start, mid, 2 * index, query_index, u);
		else
			update(mid + 1, end, 2 * index + 1, query_index, u);
		tree[index].merge(tree[2 * index], tree[2 * index + 1]);
	}
	Node query(int start, int end, int index, int left, int right) { // Never change this
		if (start > right || end < left)
			return Node();
		if (start >= left && end <= right)
			return tree[index];
		int mid = (start + end) / 2;
		Node l, r, ans;
		l = query(start, mid, 2 * index, left, right);
		r = query(mid + 1, end, 2 * index + 1, left, right);
		ans.merge(l, r);
		return ans;
	}
	void make_update(int index, int val) {  // pass in as many parameters as required
		Update new_update = Update(val); // may change
		update(0, n - 1, 1, index, new_update);
	}
	Node make_query(int left, int right) {
		return query(0, n - 1, 1, left, right);
	}
};

struct Node1 {
	long long val; // may change
	Node1() { // Identity element
		val = 0;	// may change
	}
	Node1(long long p1) {  // Actual Node
		val = p1; // may change
	}
	void merge(Node1 &l, Node1 &r) { // Merge two child nodes
		val = max(l.val , r.val);  // may change
	}
};

struct Update1 {
	long long val; // may change
	Update1(long long p1) { // Actual Update
		val = p1; // may change
	}
	void apply(Node1 &a) { // apply update to given node
		a.val = max(a.val,val); // may change
	}
};





//Union Find Algorithm Almost O(1) for reasonable size N. O(log*N) to be precise
struct UnionFind {
	int n;
	vector<int> rank;
	vector<int> parent;
	// store other info as required
	UnionFind(int n) {
		rank.resize(n);
		fill(rank.begin(), rank.end(), 0);
		parent.resize(n);
		for (int i = 0; i < n; i++) {
			parent[i] = i;
		}
	}
	int get(int a) {
		return parent[a] = (parent[a] == a ? a : get(parent[a]));
	}
	void merge(int a, int b) {
		a = get(a);
		b = get(b);
		if (a == b) {
			return;
		}
		if (rank[a] == rank[b]) {
			rank[a]++;
		}
		if (rank[a] > rank[b]) {
			parent[b] = a;
		} else {
			parent[a] = b;
		}
	}
};

void ask(string s){
	cout<<1<<" "<<s<<endl;
}

int solve(string&a,string&b,string&c,int i,int j,int n,int m,vector<vector<int>>&dp){
	if(i==n && j==m){
		return 0;
	}
	if(dp[i][j]!=-1)return dp[i][j];
	if(i==n){
		return (b[j]!=c[i+j])+solve(a,b,c,i,j+1,n,m,dp);
	}
	if(j==m){
		return (a[i]!=c[i+j])+solve(a,b,c,i+1,j,n,m,dp);
	}

	int takea=INT_MAX;
	int takeb=INT_MAX;
	takea=(a[i]!=c[i+j])+solve(a,b,c,i+1,j,n,m,dp);
	takeb=(b[j]!=c[i+j])+solve(a,b,c,i,j+1,n,m,dp);
	return dp[i][j]=min(takea,takeb);
}

signed main(){
	//  x^y = x + y - 2(x&y);
	int t;
	cin>>t;
	while(t--){
		string a,b,c;
		cin>>a>>b>>c;
		vector<vector<int>> dp(a.length()+2,vector<int>(b.length()+2,-1));
		int ans=solve(a,b,c,0,0,a.length(),b.length(),dp);
		cout<<ans<<endl;
	}
}

Answer: 2