DNA repair - HDU 2457(自动机+dp)

时间:2025-01-07 19:07:14

题目大意:给你N个DNA的串,也就是至包含'A','T','G','C'四种碱基的,这些给定的串都是带有遗传病的,然后给你一个不会超过1000的串,问你至少几个地方才能让这个串不包含遗传病,如果不论怎么修改都没用,输出'-1'

 

分析:用dp[Ni][nNode],表示长度为i时候到达第n个节点修改的最小次数,然后统计最后一层次最小次数就行了。

 

代码如下:

=============================================================================================================================

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; const int MAXN = ;
const int MAXM = ;
const int MaxSon = ;
const int oo = 1e9+; int dp[MAXN][MAXN]; struct Ac_Trie
{
int next[MAXN][MaxSon];
int Fail[MAXN], End[MAXN];
int cnt, root; int newnode()
{
for(int i=; i<MaxSon; i++)
next[cnt][i] = -;
Fail[cnt] = End[cnt] = false; return cnt++;
}
void InIt()
{
cnt = ;
root = newnode();
}
int Find(char ch)
{
if(ch == 'A')return ;
if(ch == 'T')return ;
if(ch == 'G')return ; return ;
}
void Insert(char s[])
{
int now = root; for(int i=; s[i]; i++)
{
int k = Find(s[i]); if(next[now][k] == -)
next[now][k] = newnode();
now = next[now][k];
} End[now] = true;
}
void GetFial()
{
queue<int>Q;
int now = root; for(int i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = root;
else
{
Fail[next[now][i]] = root;
Q.push(next[now][i]);
}
} while(Q.size())
{
now = Q.front();
Q.pop(); for(int i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = next[Fail[now]][i];
else
{
Fail[next[now][i]] = next[Fail[now]][i];
Q.push(next[now][i]);
}
} End[now] |= End[Fail[now]];
}
}
};
Ac_Trie ac; int main()
{
int N, t=; while(scanf("%d", &N), N)
{
char s[MAXN];
ac.InIt(); for(int i=; i<N; i++)
{
scanf("%s", s);
ac.Insert(s);
}
ac.GetFial(); scanf("%s", s+);
N = strlen(s); for(int i=; i<=N; i++)
for(int j=; j<ac.cnt; j++)
dp[i][j] = oo; dp[][] = ; for(int i=; i<N-; i++)
for(int j=; j<ac.cnt; j++)
for(int k=; k<; k++)
{
int w = dp[i][j];
int next = ac.next[j][k]; if(ac.End[next])continue; if(ac.Find(s[i+]) != k)
w++; if(dp[i+][next] > w)
dp[i+][next] = w;
} int Min = oo; for(int i=; i<ac.cnt; i++)
Min = min(Min, dp[N-][i]); if(Min == oo)
Min = -; printf("Case %d: %d\n", t++, Min);
} return ;
}