AC +オートマトンDNA修復のステートマシンdp--

DNA修復

生物学者は、最終的にDNA修復技術を発明し、それは断片が修復されたDNAを含む種々の遺伝病のものとすることができます。

簡単にするために、A 'A'、 'G'、 'C​​'、 'T' の文字列としてDNA。

修復技術は、このように、文字列に含まれる病原性フラグメントを解消する、文字列内の文字の一部を変更することです。

たとえば、私たちは「AAG」、「AGC」は、「CAG」DNA断片がDNAを修復するためには、何の病原性フラグメントを含んでいないのでことを、文字2つのDNA断片「AAGCAGは」「AGGCAC」となり変更することができますフラグメント。

まだのみ文字 'A'、 'G'、 'C​​'、 'T' を含む、修復DNA断片を留意すべきです。

ヘルプ生物学者は、DNAフラグメントを与え固定し、文字の数は、可能な限り小さく、修理中に変更されるようにしてください。

入力形式の
入力は、試験データの複数のセットを含みます。

各データ線は、最初の整数N、病原性DNA断片の数を含みます。

次のN行は、非空の文字列の長さを含む各列20は、文字列が病原性のDNA断片を示すために、唯一の「A」、「G」、「C」、「T」を含む超えません。

その後、修復されるべきDNA断片を示すためにのみ「A」、「G」、「C」、「T」を含む文字のない1000以上の非空の文字列の長さを含む行、。

最後の行で設定されたテストデータの後ろに入力の終わりを示す、0を含んでいます。

出力形式
各データ出力結果、1行毎の結果のために。

フォーム「ケースX:Y」を入力し、ここで、x(1から始まる)、yが与えられたDNA断片を修復できない場合、yは、必要な試験データの数を変更する修復過程における文字の最小数「です - 1. "

データ範囲
1 N 50 1≤N≤50
入力サンプル:
2
AAA
AAG
AAAG
2
A
TG
TGAATG
4。
A
G
C
T
AGT
0
出力サンプル:
。ケース1 :. 1
ケース2 :. 4
。ケース3:-1

ソリューション:

Dpが関数を定義し、 F , j ) F(i、j)は のi番目の位置に一致するように、私たちに代わって、答えの兆木j番目の位置を終了します。我々は位置をジャンプする前に、現在の位置と異なるウイルス缶1またはできない現在位置が対応する場合には、統計に答えの現在位置を列挙するために接尾文字に一致させることができます。

#include <bits/stdc++.h>
using namespace std;
const int N=1005;
int ne[N],tar[N],tr[N][5],cnt,n;
char str[N];
int f[N][N];
queue<int> q;
int get(char c)
{
    if (c == 'A') return 0;
    if (c == 'T') return 1;
    if (c == 'G') return 2;
    return 3;
}
void insert()
{
    int p=0;
    for(int i=0;str[i];i++){
        int t=get(str[i]);
        if(!tr[p][t]) tr[p][t]=++cnt;
        p=tr[p][t];
    }
    tar[p]=1;
}
void build()
{
    for(int i=0;i<4;i++) if(tr[0][i]) q.push(tr[0][i]);
    while(!q.empty()){
        int u=q.front(); q.pop();
        for(int i=0;i<4;i++){
            int p=tr[u][i];
            if(!p) tr[u][i]=tr[ne[u]][i];
            else {
                ne[p]=tr[ne[u]][i];
                q.push(p);
                tar[p]|=tar[ne[p]];
            }
        }
    }
}
int main()
{
    int T = 1;
    while (scanf("%d", &n), n)
    {
        memset(tr, 0, sizeof tr);
        memset(tar, 0, sizeof tar);
        memset(ne, 0, sizeof ne);
        cnt = 0;
        for (int i = 0; i < n; i ++ )
        {
            scanf("%s", str);
            insert();
        }
        build();
        scanf("%s", str + 1);
        int m = strlen(str + 1);
        memset(f, 0x3f, sizeof f);
        f[0][0] = 0;
        for (int i = 0; i < m; i ++ )
            for (int j = 0; j <= cnt; j ++ )
                for (int k = 0; k < 4; k ++ ){
                    int t = get(str[i + 1]) != k;
                    int p = tr[j][k];
                    if (!tar[p]) f[i + 1][p] = min(f[i + 1][p], f[i][j] + t);
                }

        int res = 0x3f3f3f3f;
        for (int i = 0; i <= cnt; i ++ ) res = min(res, f[m][i]);
        if (res == 0x3f3f3f3f) res = -1;
        printf("Case %d: %d\n", T ++, res);
    }
    return 0;
}
公開された181元の記事 ウォン称賛10 ビュー5057

おすすめ

転載: blog.csdn.net/weixin_42979819/article/details/104227103