Bu yanıt şu anda bir hata nedeniyle bozuldu. Yakında düzeltme ...
C, ~ 35 saniyede 2 dize
Bu, devam eden bir çalışma (korkunç dağınıklık ile gösterildiği gibi), ancak umarım bazı iyi cevaplar çıkarır!
Kod:
#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;
}
Tüm LCS hesaplamasını gerçekleştiren ilgili işlev, işlevdir LCS
. Yukarıdaki kod bu işleve kendi çağrısını zamanlayacaktır.
Farklı kaydet main.c
ve şununla derle:gcc -Ofast main.c -o FLCS
Kod, komut satırı bağımsız değişkenleriyle veya stdin aracılığıyla çalıştırılabilir. Stdin kullanırken, bir dizi dizenin ardından dizelerin kendisinin gelmesini bekler.
~ Me$ ./FLCS "12345" "23456"
2345
Size: 4
Elapsed time on LCS call: 0.000056 s
Veya:
~ Me$ ./FLCS
6
2341582491248123139182371298371239813
2348273123412983476192387461293472793
1234123948719873491234120348723412349
1234129388234888234812834881423412373
1111111112341234128469128377293477377
1234691237419274737912387476371777273
1241231212323
Size: 13
Elapsed time on LCS call: 0.001594 s
1.7Ghz Intel Core i7 ve Dennis'in sağladığı test senaryosuna sahip bir Mac OS X kutusunda, 2 dize için aşağıdaki çıktıyı alıyoruz:
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
Bu yaklaşım, burada daha önceki zorluklara yaklaşımımla çok benzer. . Önceki optimizasyona ek olarak, artık her yinelemede dizeler arasında toplam paylaşılan karakter sayısını kontrol ediyoruz ve zaten mevcut olandan daha uzun bir alt dize elde etmenin bir yolu yoksa erken çıkıyoruz.
Şimdilik, 2 dizeyi iyi işliyor ancak daha fazla çökme eğilimi gösteriyor. Daha fazla iyileştirme ve daha iyi bir açıklama!