Cod sursa(job #308)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 9 decembrie 2006 18:53:34
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.92 kb
#include <stdio.h>
const int N = 18;

int n, i, j, k, n2;
char str[N][30001];
char c;
int len[N];
int ign[N];                                    //ignored
int index[N];
int aux[30001];                                 //vector auxiliar pt KMP
int comun[N][N];
int a[N][1 << N];
int b[N][1 << N];

int precalc_kmp(int i)
{
    int m = len[i], k, q;
    aux[0] = -1;
    k = -1;
    for (q = 1; q <= m; q++)
    {
        while (k >= 0 && str[i][k + 1] != str[i][q]) k = aux[k];
        if (str[i][k + 1] == str[i][q])
            k++;
        aux[q] = k;
    }
    return 0;
}

int kmp(int i, int j, int &comun)
{
     int n = len[i], m = len[j], q, k, ret = 0;
     q = 0;
     for (k = 0; k <= n; k++)
     {
         while (q >= 0 && str[j][q + 1] != str[i][k]) q = aux[q];
         if (str[j][q + 1] == str[i][k])
             q++;
         if (q == m)
             ret=1;
     }
     comun = q + 1;
     return ret;
}

void gendrum(int i, int j)
{
    if (j == 0) return;
    printf("%s", str[index[b[i][j]]] + comun[index[i]][index[b[i][j]]]);
    gendrum(b[i][j], j - (1 << b[i][j]));
}

int main()
{
    freopen("adn.in", "rt", stdin);
    freopen("adn.out", "wt", stdout);
    scanf("%d", &n);
    for (i = 0; i < n; i++)
    {
        do
            scanf("%c", &c);
        while (c != 'A' && c != 'C' && c != 'G' && c != 'T');

        len[i] = -1;
        do
        {
            str[i][++len[i]] = c;
            scanf("%c", &c);
        }
        while (c == 'A' || c == 'C' || c == 'G' || c == 'T');
    }
    n2 = n;
    for (i = 0; i < n2; i++)
        if (!ign[i])
        {
            precalc_kmp(i);
            for (j = 0; j < n2 && !ign[i]; j++)
                if (j != i && !ign[j])
                    if (kmp(j, i, comun[j][i]))
                    {
                        ign[i] = 1;
                        n--;
                    }
        }
    for (index[0] = 0; ign[index[0]]; index[0]++);
    j = index[0];
    for (i = 1; i < n; i++)
    {
        for (j++; ign[j]; j++);
        index[i] = j;
    }
    for (i = 0; i < n; i++)
        a[i][0] = 0;
    int max, maxi;
    for (i = 1; i < 1 << n; i++)
        for (j = 0; j < n; j++)
        {
            max = maxi = -1;
            for (k = 0; k < n; k++)
                if (i & (1 << k))
                    if (comun[index[j]][index[k]] + a[k][i - (1 << k)] > max)
                    {
                        max = comun[index[j]][index[k]] + a[k][i - (1 << k)];
                        maxi = k;
                    }
            a[j][i] = max;
            b[j][i] = maxi;
        }
    max = maxi = 0;
    for (i = 0; i < n; i++)
        if (a[i][(1 << n) - 1 - (1 << i)] > max)
        {
            max = a[i][(1 << n) - 1 - (1 << i)];
            maxi = i;
        }
    printf("%s", str[index[maxi]]);
    gendrum(maxi, (1 << n) - 1 - (1 << maxi));
    return 0;
}