ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

acwing1053. 修复DNA(AC 自动机+dp)

2021-11-03 12:05:43  阅读:202  来源: 互联网

标签:AC DNA int tr ++ acwing1053 id dp define


题意

  1. 给定 n 个子串 ti 四个字符,和一个主串 s,所有字符串仅包含 A,G,C,T,问最少需要修改几个字符,才使 s 中不包含任意一个 ti 字符串。
  2. n < 50, |s|<=1000, |ti<=20|.

思路

  1. 这是 y 总讲的状态机模型,我们可以先设出 dp 方程:dp [i][j] 表示匹配 i 个字符,且已经匹配到自动机树中的编号为 j 的节点位置,
  2. 那么我们考虑状态转移:如果当前我么已经求出 dp [i][j] 的话,我们可以枚举长度为第 i+1 个字符选择 A,G,C, T 中的一个字符设为 x,进行状态递推,dp [i][j] 是可以递推出 dp [i+1][k] 这个状态的话 如果 tr [j][x] == k, 并且要求第 k 个位置没有单词结尾,那么这就是一个合法的状态转移。
  3. 补充:自动机中节点个数非常少,且待匹配的字符串非常的长的话,我们可以考虑用 矩阵快速幂 优化状态转移。

代码

#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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有