acwing1053. 修复DNA(AC 自动机+dp)
作者:互联网
题意
- 给定 n 个子串 ti 四个字符,和一个主串 s,所有字符串仅包含 A,G,C,T,问最少需要修改几个字符,才使 s 中不包含任意一个 ti 字符串。
- n < 50, |s|<=1000, |ti<=20|.
思路
- 这是 y 总讲的状态机模型,我们可以先设出 dp 方程:dp [i][j] 表示匹配 i 个字符,且已经匹配到自动机树中的编号为 j 的节点位置,
- 那么我们考虑状态转移:如果当前我么已经求出 dp [i][j] 的话,我们可以枚举长度为第 i+1 个字符选择 A,G,C, T 中的一个字符设为 x,进行状态递推,dp [i][j] 是可以递推出 dp [i+1][k] 这个状态的话 如果 tr [j][x] == k, 并且要求第 k 个位置没有单词结尾,那么这就是一个合法的状态转移。
- 补充:自动机中节点个数非常少,且待匹配的字符串非常的长的话,我们可以考虑用 矩阵快速幂 优化状态转移。
代码
#include <bits/stdc++.h>
using namespace std;
#define db double
#define ll long long
#define Pir pair<int, int>
#define fi first
#define se second
#define pb push_back
#define m_p make_pair
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
/*==========ACMer===========*/
const int N = 1005;
int n;
char s[N];
int tr[N][4], fa[N], mk[N], idx;
int dp[N][N];
int id[150];
void pre_do()
{
id['A'] = 0;
id['G'] = 1;
id['C'] = 2;
id['T'] = 3;
}
void insert()
{
int u = 0;
for (int i = 0; s[i]; i ++) {
if (tr[u][id[s[i]]] == 0) tr[u][id[s[i]]] = ++ idx;
u = tr[u][id[s[i]]];
}
mk[u] = 1;
}
void build()
{
queue<int> q;
for (int i = 0; i < 4; i ++) {
if (tr[0][i]) q.push(tr[0][i]);
}
while (q.size())
{
int u = q.front(); q.pop();
if (mk[fa[u]]) mk[u] = 1;
for (int i = 0; i < 4; i ++) {
if (tr[u][i])
fa[tr[u][i]] = tr[fa[u]][i], q.push(tr[u][i]);
else
tr[u][i] = tr[fa[u]][i];
}
}
}
void init()
{
memset(tr, 0, sizeof tr);
memset(fa, 0, sizeof fa);
memset(mk, 0, sizeof mk);
idx = 0;
}
int main()
{
pre_do();
int cas = 1;
while (scanf("%d", &n) && n)
{
init();
for (int i = 1; i <= n; i ++) {
scanf("%s", s);
insert();
}
scanf("%s", s);
int m = strlen(s);
build();
memset(dp, inf, sizeof dp);
dp[0][0] = 0;
for (int i = 0; i < m; i ++) {
for (int j = 0; j < idx; j ++) {
for (int k = 0; k < 4; k ++) {
int l = tr[j][k];
if (mk[j] || mk[l] || dp[i][j] == inf) continue;
dp[i + 1][l] = min(dp[i + 1][l], dp[i][j] + (id[s[i]] != k));
}
}
}
int ans = inf;
for (int i = 0; i < idx; i ++)
ans = min(ans, dp[m][i]);
printf("Case %d: ", cas ++);
if (ans == inf)
printf("-1\n");
else
printf("%d\n", ans);
}
return 0;
}
标签:AC,DNA,int,tr,++,acwing1053,id,dp,define 来源: https://blog.csdn.net/qq_34261446/article/details/121056406