自由文本差异的Java库

自由文本差异的Java库,java,string,text,comparison,diff,Java,String,Text,Comparison,Diff,我需要匹配两个几乎相同的长自由文本字符串;i、 e.尽可能找到索引之间的对应关系 因为这是自由文本,所以比较不应该像在代码差异中那样基于行 对Java库有什么建议吗 一个简单的例子(当然,在现实生活中,不会有额外的空格来排列东西,可能会有更复杂的挑战,比如整个子句的移动。) 这个可能很好。根据您的具体需求,组件的StringUtils类可能会有所帮助,例如: StringUtils#difference:比较两个字符串,并返回它们不同的部分 StringUtils#GetLevenshteIn

我需要匹配两个几乎相同的长自由文本字符串;i、 e.尽可能找到索引之间的对应关系

因为这是自由文本,所以比较不应该像在代码差异中那样基于行

对Java库有什么建议吗

一个简单的例子(当然,在现实生活中,不会有额外的空格来排列东西,可能会有更复杂的挑战,比如整个子句的移动。)


这个可能很好。

根据您的具体需求,组件的
StringUtils
类可能会有所帮助,例如:

  • StringUtils#difference:比较两个字符串,并返回它们不同的部分
  • StringUtils#GetLevenshteInstance:在两个字符串之间查找
这里有一个(经过轻度测试的)版本的代码,可以满足您的要求。您可以轻松地与输入并行遍历结果,以定位插入和删除

public class StringDiff {

    private static int   length(String s) { return s == null ? 0 : s.length(); }
    private static char[] chars(String s) { return s == null ? new char[0] : s.toCharArray(); }

    private final String left;
    private final String right;

    private final char[] lccs;
    private final String lcs;

    public StringDiff(String left, String right) {
        this.left = left;
        this.right = right;
        lccs = init();
        lcs = new String(lccs);
    }

    public String getLcs()  { return lcs; }
    public char[] getLccs() { return lccs.clone(); }

    private char[] init() {
        int lLength = length(left);
        int rLength = length(right);
        char[] lChars = chars(left);
        char[] rChars = chars(right);
        int [][] t = new int [lLength + 1][rLength + 1];
        for (int i = lLength - 1; i >= 0; --i) {
            for (int j = rLength - 1; j >= 0; --j) {
                if (lChars[i] == rChars[j]) {
                    t[i][j] = t[i + 1][j + 1] + 1;
                } else {
                    t[i][j] = Math.max(t[i + 1][j], t[i][j + 1]);
                }
            }
        }
        char[] result = new char[t[0][0]];
        int l = 0, r = 0, p = 0;
        while (l < lLength && r < rLength) {
            if (lChars[l] == rChars[r]) {
                result[p++] = lChars[l++];
                r++;
            } else {
                if (t[l + 1][r] > t[l][r + 1]) {
                    ++l;
                } else {
                    ++r;
                }
            }
        }
        return result;
    }

}
是:

(因为“brown”和“yellow”有共同点,等等)

修改上面的代码,将其拆分为空格(而不是字符数组),并将字符串#equals替换为==以获得查找最长公共子序列(而不是字符)的版本相对简单。对于上面的示例,该更改将产生明显的结果:

found 7 words
    'The'
    'quick'
    'fox'
    'jumped'
    'over'
    'the'
    'dog.'

(你的问题暗示了字符比较,因为你匹配了单词之间的空格。)

如果你是示例,那么你真正想做的就是-即子序列只有在它们从相同索引开始时才匹配(这与diff通常的操作方式不同)-这就是你需要做的全部工作:

import java.util.*;

class StringDiff {
    public static List<int[]> from(String s1, String s2) {
        int start = -1;
        int pos = 0;
        LinkedList<int[]> list = new LinkedList<int[]>();

        for(; pos < s1.length() && pos < s2.length(); ++pos) {
            if(s1.charAt(pos) == s2.charAt(pos)) {
                if(start < 0) start = pos;
            }
            else {
                if(start >= 0) list.add(new int[] { start, pos });
                start = -1;
            }
        }

        if(start >= 0) list.add(new int[] { start, pos });

        return list;
    }

    public static void main(String[] args) {
        for(int[] idx : from(args[0], args[1]))
            System.out.println(args[0].substring(idx[0], idx[1]));
    }
}
import java.util.*;
StringDiff类{
来自的公共静态列表(字符串s1、字符串s2){
int start=-1;
int pos=0;
LinkedList=新建LinkedList();
对于(;pos=0)list.add(newint[]{start,pos});
开始=-1;
}
}
if(start>=0)list.add(newint[]{start,pos});
退货清单;
}
公共静态void main(字符串[]args){
对于(int[]idx:from(args[0],args[1]))
System.out.println(args[0].子字符串(idx[0],idx[1]);
}
}

实际的差异实现将更加复杂。

您遇到的一个问题是,文本差异工具/库通常是逐行运行的,这意味着它们只在相同或不同的行之间进行描绘,如果它们不同,是因为插入/删除了其他行吗?请参阅Needleman-Wunsch算法的伪代码()在生物信息学中用于对齐两个DNA序列。多个空格字符只是为了显示,还是如果公共子序列从同一索引开始,您真的只想查找对应项?如果是后者,问题很简单——不需要库,只需自己编写代码@Christoph“多个空格字符只是为了显示o”-如上所述,这些字符只是为了帮助说明匹配。这不是他要求的,是吗?它应该是索引到索引的,因此不会返回ow、黄色和棕色的匹配项,因为它们不在同一索引上?
The quick ow fox jumped over the l dog.
found 7 words
    'The'
    'quick'
    'fox'
    'jumped'
    'over'
    'the'
    'dog.'
import java.util.*;

class StringDiff {
    public static List<int[]> from(String s1, String s2) {
        int start = -1;
        int pos = 0;
        LinkedList<int[]> list = new LinkedList<int[]>();

        for(; pos < s1.length() && pos < s2.length(); ++pos) {
            if(s1.charAt(pos) == s2.charAt(pos)) {
                if(start < 0) start = pos;
            }
            else {
                if(start >= 0) list.add(new int[] { start, pos });
                start = -1;
            }
        }

        if(start >= 0) list.add(new int[] { start, pos });

        return list;
    }

    public static void main(String[] args) {
        for(int[] idx : from(args[0], args[1]))
            System.out.println(args[0].substring(idx[0], idx[1]));
    }
}