git diff java 實現

經常使用git diff 但是其是如何實現的呢?
本博客簡單實現不考慮行的比較。可以比較兩個字符串

// 相當於把每一行換比較換成字符比較,道理一樣
s1='xxxxxxxxxx'
s2='yyyyyyyyyy'

首先我們把文件轉化爲兩個列表,列表的每個元素是文件的某一行:

A = [1行、2行、3行、4行、…]
B = [1行、2行、3行、4行、…]
然後我們計算A和B最長的相似元素的長度lcs(遞歸就是力量)

lcs = (A, B) ->
result = 0
if A.length is 0 or B.length is 0
result
else if A[0] is B[0]
result = 1 + lcs(A[1..], B[1..])
else
result = Math.max(lcs(A, B[1..]), lcs(A[1..], B))
(真實環境下,文件足夠大的話,會因爲遞歸太多而爆棧……)

拿到了lcs,然後根據計算lcs時找到的能對上的頭,就可以得出兩個文件最大的相同部分,用C表示,那麼,A、B就被切分成了:

A-、C、A+
B-、C、B+

然後,我們再用同樣的方法比較A-、B-,以及A+、B+,一直這樣遞歸下去,一段段地比較,最後把所有的結果拼起來。

最後使用Java實現

public class LCSTest {
    public static class Node {
        int st;
        String subTpl;
        int length;
        int op;

        public Node(int st, int length, int op) {
            this.st = st;
            this.length = length;
            this.op = op;
        }

        public Node(int st, int length, int op, String subTpl) {
            this.length = length;
            this.op = op;
            this.st = st;
            this.subTpl = subTpl;
        }

        @Override public String toString() {
            return "Node{" +
                "length=" + length +
                ", st=" + st +
                ", op=" + op +
                '}';
        }
    }

    // 下標都是偏移+1
    // 1是相同 2 是多了 3 是少了
    public static List<Node> LCS(String tpl, String str, int strSt) {
        if (tpl.length() == 0 && str.length() == 0) {
            return new ArrayList<>();
        } else if (tpl.length() == 0) {
            return new ArrayList<>(Collections.singletonList(new Node(strSt, str.length(), 2)));
        } else if (str.length() == 0) {
            return new ArrayList<>(
                Collections.singletonList(new Node(strSt, tpl.length(), 3, tpl)));
        }

        int[][] dp = new int[tpl.length() + 1][str.length() + 1];
        int maxi, maxj, maxk;
        maxi = maxj = maxk = 0;
        for (int i = 1; i <= tpl.length(); i++) {
            for (int j = 1; j <= str.length(); j++) {
                if (tpl.charAt(i - 1) == str.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    if (dp[i][j] >= maxk) {
                        maxk = dp[i][j];
                        maxi = i;
                        maxj = j;
                    }
                }
            }
        }

        List<Node> list = new ArrayList<>();
        if (maxk == 0) {
            list.add(new Node(strSt, tpl.length(), 3, tpl));
            list.add(new Node(strSt, str.length(), 2));
        } else {
            list.addAll(LCS(tpl.substring(0, maxi - maxk), str.substring(0, maxj - maxk), strSt));

            list.add(new Node(maxj - maxk, maxk, 1));

            list.addAll(
                LCS(tpl.substring(maxi, tpl.length()), str.substring(maxj, str.length()), maxj));
        }
        return list;
    }

    public static void main(String args[]) {

        String tpl = "【#company#】您的驗證碼是#code#";
        String str = "你好【啊啊啊】您的驗證碼是123";
        List<Node> list = LCS(tpl, str, 0);
        for (Node node : list) {
            if (node.op == 1) {
                System.out.println("sam:" + str.substring(node.st, node.st + node.length));
            } else if (node.op == 2) {
                System.out.println("add:" + str.substring(node.st, node.st + node.length));
            } else if (node.op == 3) {
                System.out.println("sub:" + node.subTpl);
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章