Java 2个字节数组的最长公共子序列
我想从二进制文件比较两个文件的LCS,因此我使用了常用的LCS源代码,并使用GenStr命令首先将文件的字节更改为字符串。 问题是,我收到了内存越界错误,因为比较字符串有限制,所以我计划使用存储字节的数组,然后比较它。是否可以使用LCS算法来比较两个字节数组 编辑:Java 2个字节数组的最长公共子序列,java,arrays,byte,sequences,longest-substring,Java,Arrays,Byte,Sequences,Longest Substring,我想从二进制文件比较两个文件的LCS,因此我使用了常用的LCS源代码,并使用GenStr命令首先将文件的字节更改为字符串。 问题是,我收到了内存越界错误,因为比较字符串有限制,所以我计划使用存储字节的数组,然后比较它。是否可以使用LCS算法来比较两个字节数组 编辑: 公共静态字节[]比较(字节[]x,字节[]y){ int i,j; 最终整数x_长度=x.length; 最终整数y_长度=y长度; int n=2048; int m=2048; //D[i][j]=方向,L[i][j]=LCS的
公共静态字节[]比较(字节[]x,字节[]y){
int i,j;
最终整数x_长度=x.length;
最终整数y_长度=y长度;
int n=2048;
int m=2048;
//D[i][j]=方向,L[i][j]=LCS的长度
int[][]D=新的int[n+1][m+1];
字节[][]L=新字节[n+1][m+1];//{1,2,3}
//D[i][0]=0表示0没有任何东西可以阻止您改用字节
数组。这将使用int
数组的一半内存,但其最大长度将相同:Integer.MAX_值
。如果内存不足,但未达到长度限制,则这可能会节省您的内存
如果这些数据来自文件,那么无论如何你都应该这么做。你真的不应该把它们作为完整的字符串来读取。一个字节一个字节地读取它们
但是如果文件很大(超过2GB),正确的方法是边处理文件,而不是事先读取文件,并使用文件存储正在创建的LCS数据。该算法的优点是所有访问都是本地化的:按顺序扫描输入文件(因此,预先读取它们不会带来任何好处);并且,通过在计算新值时只考虑上一行和当前行,可以非常接近顺序地写入数组(因此,将它们放在RAM中也不会获得太多好处)
这样做将允许您任意缩放文件。CPU时间将是决定因素。磁盘缓存将为您提供与先读取文件然后从RAM执行操作所获得的性能相近的性能。无需考虑算法的转换
在javanew
中,初始化为0/0.0/false/null
另一方面,对lcs的预处理不能开箱即用。但是反转数组很简单
public static byte[] compare(byte[] x, byte[] y) {
int i, j;
final int n = x.length;
final int m = y.length;
/* D[i][j] = direction, L[i][j] = Length of LCS */
int[][] D = new int[n + 1][m + 1];
byte[][] L = new byte[n + 1][m + 1]; // { 1, 2, 3 }
/* D[i][0] = 0 for 0<=i<=n */
/* D[0][j] = 0 for 0<=j<=m */
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (x[i - 1] == y[ - 1]) {
D[i][j] = D[i - 1][j - 1] + 1;
L[i][j] = 1;
} else if (D[i - 1][j] >= D[i][j - 1]) {
D[i][j] = D[i - 1][j];
L[i][j] = 2;
} else {
D[i][j] = D[i][j - 1];
L[i][j] = 3;
}
}
}
/* Backtrack */
ByteArrayOutputStream lcs = new ByteArrayOutputStream();
i = n;
j = m;
while (i != 0 && j != 0) {
switch (L[i][j]) {
case 1: /* diagonal */
lcs.write(x[i - 1]); // We want lcs reversed though.
--i;
--j;
break;
case 2: /* up */
--i;
break;
case 3: /* backward */
--j;
break;
}
}
byte[] result = lcs.toByteArray();
// Reverse:
for (i = 0, j = result.length - 1; i < j; ++i, --j) {
byte b = result[i];
result[i] = result[j];
result[j] = b;
}
return result;
}
公共静态字节[]比较(字节[]x,字节[]y){
int i,j;
最终整数n=x.长度;
最终整数m=y.长度;
/*D[i][j]=方向,L[i][j]=LCS的长度*/
int[][]D=新的int[n+1][m+1];
字节[][]L=新字节[n+1][m+1];//{1,2,3}
/*D[i][0]=0表示0如何生成两个文件的md5校验和并对其进行比较?如果您关心的是字符串长度的限制,字节数组也有类似的限制,也是有符号整数的最大值。感谢回复。至于在读取时处理LCS,我该如何做?使用链表?不,只需将文件本身用作数据结构即可cture.对于输入,打开文件,然后逐字节读取。对于输出,打开文件,逐字节写入,在需要读回内容时查找文件中的正确点。@Anonymous No,一点也不。使用BufferedInputStream
,并且无论何时需要下一个字节,都从流中读取。无需thre这只是为了避免先读取整个文件。但是LCS算法不需要所有字符串吗(在我的例子中,我使用字节)要在计算LCS之前先放入矩阵中,因此我们需要先读取所有字节?还是我错了?抱歉所有的问题,并提前感谢。@匿名不,不需要它们在矩阵中,只需要你能够在需要时获取它们。如果你看算法,它会读取每个输入序列不管你是从阵列中还是从其他东西中获取它们都是无关紧要的。
public static byte[] compare(byte[] x, byte[] y) {
int i, j;
final int n = x.length;
final int m = y.length;
/* D[i][j] = direction, L[i][j] = Length of LCS */
int[][] D = new int[n + 1][m + 1];
byte[][] L = new byte[n + 1][m + 1]; // { 1, 2, 3 }
/* D[i][0] = 0 for 0<=i<=n */
/* D[0][j] = 0 for 0<=j<=m */
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (x[i - 1] == y[ - 1]) {
D[i][j] = D[i - 1][j - 1] + 1;
L[i][j] = 1;
} else if (D[i - 1][j] >= D[i][j - 1]) {
D[i][j] = D[i - 1][j];
L[i][j] = 2;
} else {
D[i][j] = D[i][j - 1];
L[i][j] = 3;
}
}
}
/* Backtrack */
ByteArrayOutputStream lcs = new ByteArrayOutputStream();
i = n;
j = m;
while (i != 0 && j != 0) {
switch (L[i][j]) {
case 1: /* diagonal */
lcs.write(x[i - 1]); // We want lcs reversed though.
--i;
--j;
break;
case 2: /* up */
--i;
break;
case 3: /* backward */
--j;
break;
}
}
byte[] result = lcs.toByteArray();
// Reverse:
for (i = 0, j = result.length - 1; i < j; ++i, --j) {
byte b = result[i];
result[i] = result[j];
result[j] = b;
}
return result;
}