Câu trả lời này hiện đang bị hỏng do một lỗi. Khắc phục sớm ...
C, 2 chuỗi trong ~ 35 giây
Đây là một công việc đang tiến triển (như thể hiện bởi sự lộn xộn khủng khiếp), nhưng hy vọng nó sẽ đưa ra một số câu trả lời hay!
Mật mã:
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "time.h"
/* For the versatility */
#define MIN_CODEPOINT 0x30
#define MAX_CODEPOINT 0x3F
#define NUM_CODEPOINT (MAX_CODEPOINT - MIN_CODEPOINT + 1)
#define CTOI(c) (c - MIN_CODEPOINT)
#define SIZE_ARRAY(x) (sizeof(x) / sizeof(*x))
int LCS(char** str, int num);
int getshared(char** str, int num);
int strcount(char* str, char c);
int main(int argc, char** argv) {
char** str = NULL;
int num = 0;
int need_free = 0;
if (argc > 1) {
str = &argv[1];
num = argc - 1;
}
else {
scanf(" %d", &num);
str = malloc(sizeof(char*) * num);
if (!str) {
printf("Allocation error!\n");
return 1;
}
int i;
for (i = 0; i < num; i++) {
/* No string will exceed 1000 characters */
str[i] = malloc(1001);
if (!str[i]) {
printf("Allocation error!\n");
return 1;
}
scanf(" %1000s", str[i]);
str[i][1000] = '\0';
}
need_free = 1;
}
clock_t start = clock();
/* The call to LCS */
int size = LCS(str, num);
double dt = ((double)(clock() - start)) / CLOCKS_PER_SEC;
printf("Size: %d\n", size);
printf("Elapsed time on LCS call: %lf s\n", dt);
if (need_free) {
int i;
for (i = 0; i < num; i++) {
free(str[i]);
}
free(str);
}
return 0;
}
/* Some terribly ugly global variables... */
int depth, maximum, mapsize, lenmap[999999][2];
char* (strmap[999999][20]);
char outputstr[1000];
/* Solves the LCS problem on num strings str of lengths len */
int LCS(char** str, int num) {
/* Counting variables */
int i, j;
if (depth + getshared(str, num) <= maximum) {
return 0;
}
char* replace[num];
char match;
char best_match = 0;
int earliest_set = 0;
int earliest[num];
int all_late;
int all_early;
int future;
int best_future = 0;
int need_future = 1;
for (j = 0; j < mapsize; j++) {
for (i = 0; i < num; i++)
if (str[i] != strmap[j][i])
break;
if (i == num) {
best_match = lenmap[j][0];
best_future = lenmap[j][1];
need_future = 0;
if (best_future + depth < maximum || !best_match)
goto J;
else {
match = best_match;
goto K;
}
}
}
for (match = MIN_CODEPOINT; need_future && match <= MAX_CODEPOINT; match++) {
K:
future = 1;
all_late = earliest_set;
all_early = 1;
for (i = 0; i < num; replace[i++]++) {
replace[i] = strchr(str[i], match);
if (!replace[i]) {
future = 0;
break;
}
if (all_early && earliest_set && replace[i] - str[i] > earliest[i])
all_early = 0;
if (all_late && replace[i] - str[i] < earliest[i])
all_late = 0;
}
if (all_late) {
future = 0;
}
I:
if (future) {
if (all_early || !earliest_set) {
for (i = 0; i < num; i++) {
earliest[i] = (int)(replace[i] - str[i]);
}
}
/* The recursive bit */
depth++;
future += LCS(replace, num);
depth--;
best_future = future > best_future ? (best_match = match), future : best_future;
}
}
if (need_future) {
for (i = 0; i < num; i++)
strmap[mapsize][i] = str[i];
lenmap[mapsize][0] = best_match;
lenmap[mapsize++][1] = best_future;
}
J:
if (depth + best_future >= maximum) {
maximum = depth + best_future;
outputstr[depth] = best_match;
}
if (!depth) {
mapsize = 0;
maximum = 0;
puts(outputstr);
}
return best_future;
}
/* Return the number of characters total (not necessarily in order) that the strings all share */
int getshared(char** str, int num) {
int c, i, tot = 0, min;
for (c = MIN_CODEPOINT; c <= MAX_CODEPOINT; c++) {
min = strcount(str[0], c);
for (i = 1; i < num; i++) {
int count = strcount(str[i], c);
if (count < min) {
min = count;
}
}
tot += min;
}
return tot;
}
/* Count the number of occurrences of c in str */
int strcount(char* str, char c) {
int tot = 0;
while ((str = strchr(str, c))) {
str++, tot++;
}
return tot;
}
Hàm liên quan thực hiện tất cả các tính toán LCS là hàm LCS
. Đoạn mã trên sẽ gọi thời gian riêng của nó tới hàm này.
Lưu dưới dạng main.c
và biên dịch với:gcc -Ofast main.c -o FLCS
Mã có thể được chạy hoặc với các đối số dòng lệnh hoặc thông qua stdin. Khi sử dụng stdin, nó mong đợi một số chuỗi được theo sau bởi chính các chuỗi.
~ Me$ ./FLCS "12345" "23456"
2345
Size: 4
Elapsed time on LCS call: 0.000056 s
Hoặc là:
~ Me$ ./FLCS
6
2341582491248123139182371298371239813
2348273123412983476192387461293472793
1234123948719873491234120348723412349
1234129388234888234812834881423412373
1111111112341234128469128377293477377
1234691237419274737912387476371777273
1241231212323
Size: 13
Elapsed time on LCS call: 0.001594 s
Trên hộp Mac OS X có Intel Core i7 1.7Ghz và trường hợp thử nghiệm mà Dennis cung cấp, chúng tôi nhận được đầu ra sau cho 2 chuỗi:
16638018800200>3??32322701784=4240;24331395?<;=99=?;178675;866002==23?87?>978891>=9<66=381992>>7030829?25265804:=3>:;60<9384=081;08?66=51?0;509072488>2>924>>>3175?::<9199;330:494<51:>748571?153994<45<??20>=3991=<962508?7<2382?489
Size: 386
Elapsed time on LCS call: 33.245087 s
Cách tiếp cận rất giống với cách tiếp cận của tôi với thử thách trước đó, ở đây . Ngoài việc tối ưu hóa trước đó, giờ đây chúng tôi kiểm tra tổng số ký tự được chia sẻ giữa các chuỗi ở mỗi lần đệ quy và thoát sớm nếu không có cách nào để có được chuỗi con dài hơn so với những gì đã tồn tại.
Hiện tại, nó xử lý 2 chuỗi ổn nhưng có xu hướng gặp sự cố nhiều hơn. Nhiều cải tiến và một lời giải thích tốt hơn sẽ đến!