HDU 2457 DNA repair 不含模式串的最少修改次数

来源:互联网 发布:人工智能就业前景 编辑:程序博客网 时间:2024/06/06 07:08

题目来源:HDU 2457 DNA repair

题意:给你一个文本串 求最少需要修改的次数 使得文本串不包含模式串

思路:可以一位一位构造一个和文本串长度一样的字符串 就4个字符 每次4选1 如果对应的位置的字符不一样修改的次数+1 并且构造的时候不包含禁止节点

dp[i][j] 代表到文本串的前i位 在ac自动机的状态为j 最少需要修改的次数

dp[l+1][v] = min(dp[l+1][v], dp[l][i] + sum); sum的值为0或1 每次都是当前状态推后面的状态 v 是i的后续状态 v 和 i都不是禁止节点的状态

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxnode = 55*22;const int size = 4;int ch[maxnode][size];int val[maxnode];int f[maxnode];int sz;const int maxn = 1010;int dp[maxn][maxnode];char s[maxn];void init(){sz = 1;memset(ch[0], 0, sizeof(ch[0]));}int idx(char c){if(c == 'A')return 0;if(c == 'T')return 1;if(c == 'C')return 2;if(c == 'G')return 3;}void insert(char *s, int v){int u = 0, n = strlen(s);for(int i = 0; i < n; i++){int c = idx(s[i]);if(!ch[u][c]){memset(ch[sz], 0, sizeof(ch[sz]));val[sz] = 0;ch[u][c] = sz++;}u = ch[u][c];}val[u] = 1;}void getFail(){queue <int> q;f[0] = 0;for(int c = 0; c < 4; c++){int u = ch[0][c];if(u){f[u] = 0;q.push(u);}}while(!q.empty()){int r = q.front(); q.pop();for(int c = 0; c < 4; c++){int u = ch[r][c];if(!u){ch[r][c] = ch[f[r]][c];continue;}q.push(u);int v = f[r];while(v && !ch[v][c])v = f[v];f[u] = ch[v][c];val[u] |= val[f[u]];}}}int main(){int cas = 1;int n;while(scanf("%d", &n) && n){init();for(int i = 0; i < n; i++){char s[22];scanf("%s", s);insert(s, 1);}getFail();scanf("%s", s);memset(dp, -1, sizeof(dp));int ans = 999999999;dp[0][0] = 0;n = strlen(s);for(int l = 0; l < n; l++){for(int i = 0; i < sz; i++){if(val[i] || dp[l][i] == -1)continue;for(int j = 0; j < 4; j++){if(val[ch[i][j]])continue;int v = ch[i][j];int sum = 0;if(idx(s[l]) != j)sum++;if(dp[l+1][v] == -1)dp[l+1][v] = dp[l][i] + sum;elsedp[l+1][v] = min(dp[l+1][v], dp[l][i] + sum);if(l + 1 == n)ans = min(ans, dp[l+1][v]);}}}printf("Case %d: ", cas++);if(ans == 999999999)printf("-1\n");elseprintf("%d\n", ans);}return 0;}


 

0 0
原创粉丝点击