我想比较二进制文件中两个文件的LCS,因此我使用了常用的LCS源代码,并使用GenStr命令将文件的字节首先更改为String。 问题是,我收到内存超出绑定错误,因为比较String有限制,因此我打算使用存储字节的数组然后比较它。是否可以使用LCS算法来比较两个字节数组?
编辑:
public static byte[] Compare(byte[] x, byte[] y) {
int i, j;
final int x_length = x.length;
final int y_length = y.length;
int n = 2048;
int m = 2048;
// 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[j - 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]); // Unreversed LCS
--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;
//While not end of file
while(n < x_length && m < y_length){
if(n+2048 < x.length){
n = n+2048;
} else {
n = x.length;
}
if(m+2048 < y.length){
m = m+2048;
} else {
m = y.length;
}
// D[i][j] = direction, L[i][j] = Length of LCS
int[][] D_new = new int[n + 1][m + 1];
byte[][] L_new = 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 = i+2048; i <= n; i++) {
for (j = j+2048; j <= m; j++) {
if (x[i - 1] == y[j - 1]) {
D_new[i][j] = D_new[i - 1][j - 1] + 1;
L_new[i][j] = 1;
} else if (D_new[i - 1][j] >= D_new[i][j - 1]) {
D_new[i][j] = D_new[i - 1][j];
L_new[i][j] = 2;
} else {
D_new[i][j] = D_new[i][j - 1];
L_new[i][j] = 3;
}
}
}
// Backtrack
ByteArrayOutputStream lcs_next = new ByteArrayOutputStream();
i = n;
j = m;
while (i != 0 && j != 0) {
switch (L[i][j]) {
case 1: // diagonal
lcs_next.write(x[i - 1]); // Unreversed LCS
--i;
--j;
break;
case 2: // up
--i;
break;
case 3: // backward
--j;
break;
}
}
byte[] result_new = lcs_next.toByteArray();
// Reverse:
for (i = 0, j = result_new.length - 1; i < j; ++i, --j) {
byte b = result_new[i];
result_new[i] = result_new[j];
result_new[j] = b;
}
return result_new;
Arrays.fill(D_new, null);
Arrays.fill(L_new, null);
Arrays.fill(result_new, null);
lcs_next.reset();
}
}
我试过,但由于某些错误,我们无法检查是否可以使用此功能。
问题:
return result
)和行(return result_new
)中追加lcs?Array.fill(D_new, null)
和Array.fill(L_new, null)
无效)?提前谢谢
答案 0 :(得分:1)
没有什么可以阻止你使用byte
数组。这将使用int
数组的一半内存,但它的最大长度将是相同的:Integer.MAX_VALUE
。如果你的RAM用完了,但没有达到长度限制,那么这可能会省你。
如果这些来自文件,那么那就是你应该做的事情。你真的不应该像整个字符串那样阅读它们。逐字节读取它们。
但如果文件很大(超过2GB),正确处理文件,而不是事先读取文件,并使用文件存储,正确的方法您正在创建的LCS数据。该算法的优点在于所有访问都是本地化的:您按顺序扫描输入文件(因此您无法提前获取任何内容);并且你通过在计算新值时仅考虑前一行和当前行来编写非常接近顺序的数组(因此,通过将它们放在RAM中也没有获得太多收益)。
这样做可以让你随意缩放文件。然后CPU时间将成为决定因素。通过首先读取文件并从RAM中执行操作,磁盘缓存将使您获得与之相同的性能。
答案 1 :(得分:0)
没有算法考虑的转换。
在java new
中初始化为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;
}