AC + 자동 장치 DNA 수리 상태 머신 dp--

DNA 수리

마지막으로 DNA 수리 기술을 발명 생물 학자, 그것은 DNA 조각을 수리했다 포함하는 다양한 유전 질환이 될 수 있습니다.

는 A 'A'와 같은 단순화, DNA의 경우, 'G', 'C', 'T'문자열.

수리 기술은 따라서 문자열에 포함 된 병원성 조각을 제거, 문자열에있는 문자의 일부를 변경하는 것입니다.

예를 들어, 우리는 그래서 "AAG"은 "AGC"는 "CAG"DNA 단편은 DNA를 복구하기 위해 더 병원성 단편을 포함하지 않는, 문자 두 DNA 단편 "AAGCAG"는 "AGGCAC"을하게 변경할 수 단편.

여전히 문자 'A', 'G', 'C', 'T'를 포함, 수리 DNA 조각을 주목해야한다.

제발 도움말 생물 학자들은 DNA 단편을 주어 수정 한 문자의 수는 가능한 한 작게 수리시 변경 될 수 있습니다.

입력 포맷
입력은 테스트 데이터의 복수의 세트를 포함한다.

각 데이터 선에는 제 정수 N, 병원성 DNA 조각의 수를 포함한다.

다음 N 개의 행은 비어 있지 않은 문자열 길이를 포함하는 각 행 (20)은, 상기 문자열이 병원체의 DNA 단편을 표시하기 만 'A', 'G', 'C', 'T'를 포함 초과하지 않는다.

그리고, 'C', 'T'는, DNA 단편을 표시하게 만 'A', 'G'를 포함하는 문자의 공백이 아닌 열 (1000) 이하의 길이를 포함하는 라인을 수리한다.

마지막 행 세트 시험 뒤에 데이터 입력의 종료를 나타내는 0을 포함한다.

출력 포맷
각각 출력되는 데이터 A는 결과, 각각의 결과에 대한 하나의 행.

형태 "케이스 X : Y"를 입력, 여기서, x (1부터), Y가 소정의 DNA 단편을 복구 할 수없는 경우, Y는, 필요한 테스트 데이터의 수를 변경하는 수리 공정의 최소 문자 번호 "입니다 - 1. "

데이터 범위
1 (50) 1≤N≤50
입력 샘플 :
2
AAA
AAG
AAAG
2TGTGAATG4.GCTAGT0출력 샘플 :. 사례 1 :. 1케이스 (2) :. 4. 사례 3 : -1













해결 방법 :

DP는 함수를 정의, 에프 ( 나는 , j ) F (I, J) 우리 대신은 i 번째 위치와 대답의 끝 조원 트리 j 번째 위치하였습니다. 그래서 우리는 위치, 통계에 대한 대답의 현재 위치를 열거하는 접미사 문자에 일치 할 수 점프하기 전에 경우 다른 바이러스에 현재 위치와 현재 위치의 대응은 할 수있는 일 또는 수 없습니다.

#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