Cod sursa(job #1098408)

Utilizator NaniteNanite Nanite Data 4 februarie 2014 19:53:12
Problema ADN Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.6 kb
#include <cstdio>
#include <cstring>
#include <cstdlib>

const unsigned short maxN = 18;
const unsigned int maxDNASequenceLength = 30000, L = maxN*maxDNASequenceLength;
const char *in = "adn.in", *out = "adn.out";

long graph[maxN][maxN];
unsigned int N;
char DNA[maxN][L];
long kmpTable[L];
unsigned int mask;

struct {
    void createKMPTable(char *pattern) {
        long k = -1, patternLength = strlen(pattern);
        memset(kmpTable, 0, L);
        kmpTable[0] = k;

        for ( long i = 1; i < patternLength; i++) {
            while (k > -1 && pattern[k+1] != pattern[i])
                k = kmpTable[k];
            if (pattern[i] == pattern[k+1])
                k++;
            kmpTable[i] = k;
        }
    }

    long kmpSearch(char *target, char *pattern) {
    createKMPTable(pattern);

    long k = -1, targetLength = strlen(target), patternLength = strlen(pattern);

    for (long i = 0; i < targetLength; i++) {
        while (k > -1 && pattern[k+1] != target[i]) {
            k = kmpTable[k];
        }
        if (target[i] == pattern[k+1]) {
            k++;
        }
        if (k == patternLength - 1) {
            return -1;
        }
    }

    return k+1;
    }
}KMP;



bool eliminated(unsigned int n) {
    return mask & (1 << n);
}

void eliminate(unsigned int n) {
    for(unsigned int i = 0; i < N; i++) {
        graph[i][n] = -1;
    }
    mask |= (1 << n);
}

void read() {
    FILE *f = fopen(in, "r");

    fscanf(f, "%u", &N);

    for(unsigned int i = 0; i < N; i++) {
        fscanf(f, "%s", DNA[i]);
    }
}

void write(char c[]) {
    FILE *f = fopen(out, "w");

    fprintf(f, "%s", c);
}

void createGraph() {
    for(unsigned int i = 0; i < N; i++) {
        graph[i][i] = -1;
    }

    for(unsigned int i = 0; i < N; i++) {
        for(unsigned int j = 0; j < N; j++) {
            if(i != j && !eliminated(i) && !eliminated(j)) {
                graph[i][j] = KMP.kmpSearch(DNA[i], DNA[j]);
                if(graph[i][j] == -1) {
                    eliminate(j);
                }
            }
        }
    }
}

void copyGraphLine(unsigned int lineA, unsigned int lineB) {
    for(unsigned int i = 0; i < N; i++) {
        graph[lineB][i] = graph[lineA][i];
    }
}

void init(unsigned int &x, unsigned int &y) {
    x = 0; y = 0;
    while(eliminated(x)) {
        x++;
    }
    while(eliminated(y) || x == y) {
        y++;
    }
}

struct Vector2u {
    unsigned int x,y;
    Vector2u(unsigned int x, unsigned int y) {
        this->x = x;
        this->y = y;
    }
};

Vector2u* getMax() {
    unsigned int maxX = 0, maxY = 0;

    init(maxX, maxY);
    for(unsigned int j = 0; j < N; j++) {
        if(!(eliminated(j))) {
            for(unsigned int k = 0; k < N; k++) {
                if(!(eliminated(k)) && graph[j][k] > graph[maxX][maxY]) {
                    maxX = j;
                    maxY = k;
                }
            }
        }
    }

    return new Vector2u(maxX, maxY);
}

void mergeDNASequences() {
    unsigned int i = 0, w;
    Vector2u* max;

    for(unsigned int j = 0; j < N; j++) {
        if(eliminated(j)) {
            i++;
        }
    }
    for(; i < N-1; i++) {
        max = getMax();
        strcat(DNA[max->x], DNA[max->y] + graph[max->x][max->y]);
        copyGraphLine(max->y, max->x);
        eliminate(max->y);

        w = max->x;
        delete max;
    }

    write(DNA[w]);
}

void printGraph() {
    for(unsigned int i = 0; i < N; i++) {
        for(unsigned int j = 0; j < N; j++) {
            printf("%li ", graph[i][j]);
        }
        printf("\n");
    }
}

int main() {
    read();
    createGraph();
    mergeDNASequences();
//    printGraph();

    return 0;
}