C ++ 75.0
该程序旨在使用任意文本字符串。它们的长度可以不同,只要不超过13824个字符即可。它使用1897个16位整数,相当于949个32位整数。最初我是用C编写的,但是后来意识到没有读取行的功能。
第一个命令行参数应该是文件名。如果存在第二个参数,则会打印编辑摘要。文件中的第一行将被忽略,而第二和第三行是字符串。
该算法是常规算法的双重阻止版本。它执行的操作次数基本相同,但是准确度当然要低得多,因为如果将公共子序列拆分到块的边缘,则会损失很多潜在的节省。
#include <cstring>
#include <inttypes.h>
#include <iostream>
#include <fstream>
#define M 24
#define MAXLEN (M*M*M)
#define SETMIN(V, X) if( (X) < (V) ) { (V) = (X); }
#define MIN(X, Y) ( (X) < (Y) ? (X) : (Y) )
char A[MAXLEN+1], B[MAXLEN+1];
uint16_t d0[M+1][M+1], d1[M+1][M+1], d2[M+1][M+1];
int main(int argc, char**argv)
{
if(argc < 2)
return 1;
std::ifstream fi(argv[1]);
std::string Astr, Bstr;
for(int i = 3; i--;)
getline(fi, i?Bstr:Astr);
if(!fi.good()) {
printf("Error reading file");
return 5;
}
if(Astr.length() > MAXLEN || Bstr.length() > MAXLEN) {
printf("String too long");
return 7;
}
strcpy(A, Astr.c_str());
strcpy(B, Bstr.c_str());
uint16_t lA = Astr.length(), lB = Bstr.length();
if(!lA || !lB) {
printf("%d\n", lA|lB);
return 0;
}
uint16_t nbA2, nbB2, bA2, bB2, nbA1, nbB1, bA1, bB1, nbA0, nbB0, bA0, bB0; //block, number of blocks
uint16_t iA2, iB2, iA1, iB1, jA2, jB2, jA1, jB1; //start, end indices of block
nbA2 = MIN(M, lA);
nbB2 = MIN(M, lB);
for(bA2 = 0; bA2 <= nbA2; bA2++) {
iA2 = lA * (bA2-1)/nbA2, jA2 = lA * bA2/nbA2;
for(bB2 = 0; bB2 <= nbB2; bB2++) {
if(!(bA2|bB2)) {
d2[0][0] = 0;
continue;
}
iB2 = lB * (bB2-1)/nbB2, jB2 = lB * bB2/nbB2;
d2[bA2][bB2] = ~0;
if(bB2)
SETMIN(d2[bA2][bB2], d2[bA2][bB2-1] + (jB2-iB2));
if(bA2)
SETMIN(d2[bA2][bB2], d2[bA2-1][bB2] + (jA2-iA2));
if(bA2 && bB2) {
nbA1 = MIN(M, jA2-iA2);
nbB1 = MIN(M, jB2-iB2);
for(bA1 = 0; bA1 <= nbA1; bA1++) {
iA1 = iA2 + (jA2-iA2) * (bA1-1)/nbA1, jA1 = iA2 + (jA2-iA2) * bA1/nbA1;
for(bB1 = 0; bB1 <= nbB1; bB1++) {
if(!(bA1|bB1)) {
d1[0][0] = 0;
continue;
}
iB1 = iB2 + (jB2-iB2) * (bB1-1)/nbB1, jB1 = iB2 + (jB2-iB2) * bB1/nbB1;
d1[bA1][bB1] = ~0;
if(bB1)
SETMIN(d1[bA1][bB1], d1[bA1][bB1-1] + (jB1-iB1));
if(bA1)
SETMIN(d1[bA1][bB1], d1[bA1-1][bB1] + (jA1-iA1));
if(bA1 && bB1) {
nbA0 = jA1-iA1;
nbB0 = jB1-iB1;
for(bA0 = 0; bA0 <= nbA0; bA0++) {
for(bB0 = 0; bB0 <= nbB0; bB0++) {
if(!(bA0|bB0)) {
d0[0][0] = 0;
continue;
}
d0[bA0][bB0] = ~0;
if(bB0)
SETMIN(d0[bA0][bB0], d0[bA0][bB0-1] + 1);
if(bA0)
SETMIN(d0[bA0][bB0], d0[bA0-1][bB0] + 1);
if(bA0 && bB0)
SETMIN(d0[bA0][bB0], d0[bA0-1][bB0-1] + (A[iA1 + nbA0 - 1] != B[iB1 + nbB0 - 1]));
}
}
SETMIN(d1[bA1][bB1], d1[bA1-1][bB1-1] + d0[nbA0][nbB0]);
}
}
}
SETMIN(d2[bA2][bB2], d2[bA2-1][bB2-1] + d1[nbA1][nbB1]);
}
}
}
printf("%d\n", d2[nbA2][nbB2]);
if(argc == 2)
return 0;
int changecost, total = 0;
for(bA2 = nbA2, bB2 = nbB2; bA2||bB2; ) {
iA2 = lA * (bA2-1)/nbA2, jA2 = lA * bA2/nbA2;
iB2 = lB * (bB2-1)/nbB2, jB2 = lB * bB2/nbB2;
if(bB2 && d2[bA2][bB2-1] + (jB2-iB2) == d2[bA2][bB2]) {
total += changecost = (jB2-iB2);
char tmp = B[jB2];
B[jB2] = 0;
printf("%d %d deleted {%s}\n", changecost, total, B + iB2);
B[jB2] = tmp;
--bB2;
} else if(bA2 && d2[bA2-1][bB2] + (jA2-iA2) == d2[bA2][bB2]) {
total += changecost = (jA2-iA2);
char tmp = B[jA2];
A[jA2] = 0;
printf("%d %d inserted {%s}\n", changecost, total, A + iA2);
A[jA2] = tmp;
--bA2;
} else {
total += changecost = d2[bA2][bB2] - d2[bA2-1][bB2-1];
char tmpa = A[jA2], tmpb = B[jB2];
B[jB2] = A[jA2] = 0;
printf("%d %d changed {%s} to {%s}\n", changecost, total, B + iB2, A + iA2);
A[jA2] = tmpa, B[jB2] = tmpb;
--bA2, --bB2;
}
}
return 0;
}
for(int i=0;i<=5;i++)
被允许的,因为它存储数据i
?