Problem: 2050E - Three Strings
Language: java

Solution 1 (runtime: 156 ms):
import java.util.*;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;

public class E_Three{
    public static void main(String[] args) throws IOException{
        InputReader sc= new InputReader (System.in);
        int t=sc.readInt();
        while(t-->0){
            
          String a=sc.readString();
          String b=sc.readString();
          String c=sc.readString();
          int max=(int)1e9;
          int n=a.length();
          int m=b.length();
          int[][] dp=new int[n+1][m+1];
          for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++){
                dp[i][j]=max;
            }
          }
          dp[0][0]=0;
          for(int i=0;i<n;i++){
            dp[i+1][0]=dp[i][0]+(a.charAt(i)==c.charAt(i)?0:1);
          }
          for(int j=0;j<m;j++){
            dp[0][j+1]=dp[0][j]+(b.charAt(j)==c.charAt(j)?0:1);
          }
          for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                dp[i][j]=Math.min(dp[i-1][j]+(a.charAt(i-1)==c.charAt(i+j-1)?0:1),dp[i][j-1]+(b.charAt(j-1)==c.charAt(i+j-1)?0:1));
            }
          }
          System.out.println(dp[n][m]);



          
            

           
            
            



            
            
            
            

            
            
            
           
            
           
           

            

           


           
           
        


    }

}
public static int countOccurence(String s1,String s2){
    int n=s1.length();
    int m=s2.length();
    int [][] dp=new int[n+1][m+1];
    for(int i=0;i<=m;i++){
        dp[0][i]=0;
    }
    for(int i=0;i<=n;i++){
        dp[i][0]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s1.charAt(i-1)==s2.charAt(j-1)){
                dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
            }
            else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    return dp[n][m];
}
public static int solve(int[] a,int x){
    int [] count=new int[a.length+1];
    int n=count.length;
    for(int i:a){
        if(i<count.length){
            count[i]++;
        }
    }
    int result=0;
    while(count[result]!=0){
        if(result+x<n){
            count[result+x]+=count[result]-1;
        }
        result++;
    }
    return result;
}

public static BigInteger factorial (int n){
    BigInteger result=BigInteger.ONE;
    for(int i=1;i<=n;i++){
        result=result.multiply(BigInteger.valueOf(i));
    }
    return result;
}
public static int [] count(int[] p,int n,String s){
    boolean [] visited=new boolean[n+1];
    int [] zeroCount=new int[n+1];
    for(int i=1;i<=n;i++){
        if(!visited[i]){
            List<Integer> cycle=new ArrayList<>();
            int curr=i;
            while(!visited[curr]){
                visited[curr]=true;
                cycle.add(curr);
                curr=p[curr];
            }
            int count=0;
            for(int ind:cycle){
                if(s.charAt(ind-1)=='0'){
                    count++;
                }
            }
            for(int ind:cycle){
                zeroCount[ind]=count;
            }
        }
        
    }
    return zeroCount;
}
public static int gcd(int a,int b){
    if(b==0){
        return a;
    }
    return gcd(b,a%b);
}
public static boolean isPrime(int n){
    boolean isPrime=true;
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            isPrime=false;
            break;
        }
    }
    return isPrime;
}
   
static final class InputReader {
        private final InputStream stream;
        private final byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
 
        public InputReader(InputStream stream) {
            this.stream = stream;
        }
 
        private int read() throws IOException {
            if (curChar >= numChars) {
                curChar = 0;
                numChars = stream.read(buf);
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }
 
        public final int readInt() throws IOException {
            return (int)readLong();
        }
 
        public final long readLong() throws IOException {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
                if (c == -1) throw new IOException();
            }
            boolean negative = false;
            if (c == '-') {
                negative = true;
                c = read();
            }
            long res = 0;
            do {
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return negative ? -res : res;
        }
 
        public final String readString() throws IOException {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            StringBuilder res = new StringBuilder();
            do {
                res.append((char)c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }
public final char readChar() throws IOException {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            return (char) c;
        }
 
        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
    }
 
}


Solution 2 (runtime: 202 ms):
import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.util.*;



public class Main {



    static int mod = 998__244______________________________________________________353;



    static int inf = (int) 2e9;



    static long infL = (long) 9e18;

    private static final int N = (int) (2e5+10);

    static int []f = new int[N];

    static int []las = new int[N];

    static int []pre = new int[N];



    static int []log = new int[N];





    static Pair<Integer,Integer> []pair = new Pair[N];

    static int n,k;



    static int[] dx = new int[]{-1,1,0,0};

    static int[] dy = new int[]{0,0,-1,1};

    static int [][] dp = new int[2025][2025];

    private static void solve(){

        String a = inStr(),b = inStr(),c = inStr();

        dp[0][0] = 0;

        for(int i=0;i<=a.length();i++){

            for(int j=0;j<=b.length();j++){

                int res = inf;

                if(i + j ==0)continue;

                if(i != 0){

                    res = Math.min(res,dp[i-1][j] + (a.charAt(i-1) == c.charAt(i + j-1)? 0 : 1));//决策a[i-1] 这个位置

                }

                if(j != 0){

                    res = Math.min(res,dp[i][j-1] + (b.charAt(j-1) == c.charAt(i + j-1)? 0 : 1));

                }

                dp[i][j] = res;

            }

        }

        println(dp[a.length()][b.length()]);

    }





    public static void main(String[] args) {

        for(int i=2;i<N;i++){

            log[i] = log[i/2] + 1;

        }

        int t = 1;

        t = in();

        while (t-- > 0) {

            solve();

        }

    }





    private static class GcdST{



        private static final int[][] st = new int[35][200020];





        public void init(int[] f,int n){

//            for(int k=0;k<=log[n]+1;k++){

//                for(int i=1;i + (1<<k) - 1 <=n ;i++){

//                    if(k==0)st[i][k] = f[i];

//                    else {

//                        st[i][k] = gcd(st[i][k-1],st[i+(1<<(k-1))][k-1]);

//                    }

//                }

//            }

            for(int k=0;k<=log[n]+1;k++){

                for(int i=1;i + (1<<k) - 1 <=n ;i++){

                    if(k==0)st[k][i] = f[i];

                    else {

                        st[k][i] = gcd(st[k-1][i],st[k-1][i+(1<<(k-1))]);

                    }

                }

            }



        }



        public int get(int l,int r){

            if(l==r){

                return st[0][l];

            }

            int x = r - l + 1;

            int res = gcd(st[log[x]][l],st[log[x]][r - (1<<log[x]) + 1]);

//            int res = 0,c = 0,base = 1;

//            while(x > 0){

//                if((x & 1) == 1){

//                    res = gcd(res,st[l][c]);

//                    l += base; // x x x x

//                }

//                x /= 2;

//                c++;

//                base *= 2;

//            }

//            for (int k = 25;k>=0;k--){

//                if(((x >> k) & 1) == 1){

//                    res = gcd(res,st[l][k]);

//                    l += 1<<k; // x x x x

//                }

//            }

            return res;

        }







    }





    private static class SegTree{



        private static class Node{

            int l,r;

            long max,min;

        }

        final Node []tr;

        public SegTree(int n){

            tr = new Node[n << 2];

            for (int i = 0; i < tr.length; i++) {

                tr[i] = new Node(); // 初始化所有节点

            }

        }

        public void init(int idx,int l,int r){

            tr[idx].l = l;

            tr[idx].r = r;

            if (l == r) { // 叶节点

                tr[idx].max = -inf;

                tr[idx].min = inf;

                return;

            }

            int mid = (l + r) >> 1;

            init(idx * 2, l, mid ); // 左子树

            init(idx * 2 + 1, mid + 1, r); // 右子树

            pushUp(idx); // 合并子树信息

        }

        // 合并子节点信息

        private void pushUp(int idx) {

            tr[idx].max = Math.max(tr[idx * 2].max, tr[idx * 2 + 1].max);

            tr[idx].min = Math.min(tr[idx * 2].min, tr[idx * 2 + 1].min);

        }





        // 区间查询最大值和最小值

        public long[] query(int l, int r, int idx) {

            if (tr[idx].l >= l && tr[idx].r <= r) { // 当前节点区间完全包含在查询区间中

                return new long[]{tr[idx].max, tr[idx].min};

            }

            int mid = (tr[idx].l + tr[idx].r) >> 1;

            long maxVal = Long.MIN_VALUE;

            long minVal = Long.MAX_VALUE;

            if (l <= mid) { // 查询左子树

                long[] leftRes = query(l, r, idx * 2);

                maxVal = leftRes[0];

                minVal = leftRes[1];

            }

            if (r > mid) { // 查询右子树

                long[] rightRes = query(l, r, idx * 2 + 1);

                maxVal = Math.max(maxVal, rightRes[0]);

                minVal = Math.min(minVal, rightRes[1]);

            }

            return new long[]{maxVal, minVal};

        }



        // 单点更新

        public void update(int idx, int pos, int value) {

            if (tr[idx].l == tr[idx].r) { // 找到目标叶节点

                tr[idx].max = tr[idx].min = value;

                return;

            }

            int mid = (tr[idx].l + tr[idx].r) >> 1;

            if (pos <= mid) { // 更新左子树

                update(idx * 2,pos, value);

            } else { // 更新右子树

                update(idx * 2 + 1,pos, value);

            }

            pushUp(idx); // 更新当前节点

        }



    }



    //  -===-      MATH       -===-  //



    static int fact(int n) {

        int r = 1;

        for (int i = 1; i <= n; i++) {

            r = (int) (((long) r * i) % mod);

        }

        return r;

    }



    static int C(int n, int k) {

        return (int) (((((long) fact(n) * pow(fact(k), mod - 2)) % mod) * pow(fact(n - k), mod - 2)) % mod);

    }



    static int gcd(int i1, int i2) {

        if (i2 == 0) return i1;

        return gcd(i2, i1 % i2);

    }



    static long gcd(long i1, long i2) {

        if (i2 == 0) return i1;

        return gcd(i2, i1 % i2);

    }



    static int pow(int x, int y) {

        x = x % mod;

        if (x == 0) return 0;

        int r = 1;

        while (y > 0) {

            if ((y & 1) != 0) r = (int) (((long) r * x) % mod);

            y /= 2;

            x = (int) (((long) x * x) % mod);

        }

        return r % mod;

    }



    static void swap(int[] a, int i, int j) {

        int tmp = a[i];

        a[i] = a[j];

        a[j] = tmp;

    }



    static int digitSum(long n) {

        int r = 0;

        while (n != 0) {

            r += (int) (n % 10);

            n /= 10;

        }

        return r;

    }



    //  -===- DATA STRUCTURES -===-  //



    static class UnionFind {



        int[] p, rank, min, max, sz;

        int n, c;



        UnionFind(int n) {

            this.n = n;

            p = new int[n];

            rank = new int[n];

            min = new int[n];

            max = new int[n];

            sz = new int[n];

            for (int i = 0; i < p.length; i++) {

                p[i] = i;

                min[i] = i;

                max[i] = i;

                sz[i] = 1;

            }

        }



        int find(int a) {

            return p[a] = (p[a] == a ? a : find(p[a]));

        }



        void union(int a, int b) {

            a = find(a);

            b = find(b);

            if (a == b) return;

            if (rank[a] > rank[b]) {

                p[b] = a;

                max[a] = Math.max(max[a], max[b]);

                min[a] = Math.min(min[a], min[b]);

                sz[a] += sz[b];

            } else {

                p[a] = b;

                max[b] = Math.max(max[b], max[a]);

                min[b] = Math.min(min[b], min[a]);

                sz[b] += sz[a];

                if (rank[a] == rank[b]) {

                    rank[b]++;

                }

            }

            c--;

        }

    }



    private static class Pair<F, S> {



        int index;



        F first;

        S second;



        public Pair(F f, S s) {

            this.first = f;

            this.second = s;

        }



        public F getFirst() {

            return first;

        }



        public S getSecond() {

            return second;

        }



        public void setFirst(F first) {

            this.first = first;

        }



        public void setSecond(S second) {

            this.second = second;

        }



        public int getIndex() {

            return index;

        }



        public void setIndex(Integer index) {

            this.index = index;

        }



        @Override

        public String toString(){

            return first.toString() + ',' + second.toString();

        }



    }





    //  -===-      IN      -===-  //

    static StringTokenizer STT;



    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));



    static PrintStream out = System.out;



    static String inStr() {

        while (STT == null || !STT.hasMoreElements()) {

            try {

                STT = new StringTokenizer(br.readLine());

            } catch (IOException e) {

                throw new RuntimeException(e);

            }

        }

        return STT.nextToken();

    }



    static int in() {

        return Integer.parseInt(inStr());

    }



    static long inLong() {

        return Long.parseLong(inStr());

    }



    static double inDouble() {

        return Double.parseDouble(inStr());

    }



    static String inLine() {

        String s;

        try {

            if (STT != null && STT.hasMoreTokens()) {

                s = STT.nextToken("\n");

            } else {

                s = br.readLine();

            }

        } catch (IOException e) {

            throw new RuntimeException(e);

        }

        return s;

    }



    static long[] inArrLong() {

        String[] split = inLine().split(" ");

        long[] a = new long[split.length];

        for (int i = 0; i < a.length; i++) {

            a[i] = Long.parseLong(split[i]);

        }

        return a;

    }



    static int[] inArr() {

        String s = inLine();

        String[] split = s.split(" ");

        int[] a = new int[split.length];

        for (int i = 0; i < a.length; i++) {

            a[i] = Integer.parseInt(split[i]);

        }

        return a;

    }



    //  -===-      PRINT      -===-  //



    static void YES() {

        out.println("YES");

    }



    static void NO() {

        out.println("NO");

    }



    static void println() {

        out.println();

    }



    static void println(int a) {

        out.println(a);

    }



    static void print(int a) {

        out.print(a);

    }



    static void println(long a) {

        out.println(a);

    }



    static void print(long a) {

        out.print(a);

    }



    static void println(double a) {

        out.println(a);

    }



    static void print(double a) {

        out.print(a);

    }



    static void println(String a) {

        out.println(a);

    }



    static void print(String a) {

        out.print(a);

    }



    static void print(int[] a) {

        for (int i = 0; i < a.length - 1; i++) {

            out.print(a[i] + " ");

        }

        if (a.length > 0) {

            out.println(a[a.length - 1]);

        }

    }



    static void print(List<?> l) {

        for (int i = 0; i < l.size() - 1; i++) {

            out.print(l.get(i) + " ");

        }

        if (!l.isEmpty()) {

            out.println(l.get(l.size() - 1));

        }

    }





    public static class D {

        private final int[] dArray; // 离散化后的数组



        public int index;



        // 初始化方法

        public D(int[] oArray,int n) {

            // 1. 去重

            Set<Integer> set = new HashSet<>();

            for(int i=1;i<=n;i++){

                set.add(oArray[i]);

            }



            // 2. 转换为数组并排序

            dArray = new int[set.size()+1];

            index = 0;

            for (int num : set) {

                dArray[++index] = num;

            }

            Arrays.sort(dArray,1,index+1);

        }



        public int getOld(int x){

            return dArray[x];

        }



        // 获取离散化后的值（二分查找实现）

        public int get(int target) {

            int left = 1;

            int right = index;



            while (left <= right) {

                int mid = left + (right - left) / 2;

                if (dArray[mid] == target) {

                    return mid; // 返回下标 + 1（假设下标从 1 开始）

                } else if (dArray[mid] < target) {

                    left = mid + 1;

                } else {

                    right = mid - 1;

                }

            }



            return -1; // 如果未找到，返回 -1

        }



    }



}