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. "
데이터 범위
입력 샘플 :
2
AAA
AAG
AAAG
2TGTGAATG4.GCTAGT0출력 샘플 :. 사례 1 :. 1케이스 (2) :. 4. 사례 3 : -1
해결 방법 :
DP는 함수를 정의, 우리 대신은 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;
}