zoukankan      html  css  js  c++  java
  • 修复DNA

    题目描述

    给定一些字符串,再给定一个母串,问通过单点修改母串使其不包含任何一个给定字符串的最小操作数是多少?

    范围

    \(N \leq 50,|S| \leq 1000\)

    题解

    \(AC自动机,dp\)

    \(f_{i,j}\)表示当前在处理\(DNA\)序列第\(i\)位,\(AC\)自动机上第\(j\)个节点时的答案。

    对于\(DNA\)序列的某一位,枚举他的所有方案\(A,G,C,T\),找到\(Trie\)树上与之对应的节点,进行\(dp\)转移:

    \(f_{i,p} = max(f_{i,p},f_{i - 1,j} + 1\or0)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1010;
    int t[N][4];
    int fl[N];
    int cnt[N];
    int q[N];
    
    char s[N];
    int f[N][N];
    
    int n,idx;
    
    int check(char c) {
    	if(c == 'A') return 0;
    	else if(c == 'G') return 1;
    	else if(c == 'C') return 2;
    	else return 3;
    }
    
    void insert(char *s) {
    	int p = 0;
    	for(int i = 0;s[i]; ++i) {
    		int num = check(s[i]);
    		if(!t[p][num]) t[p][num] = ++idx;
    		p = t[p][num];
    	}
    	cnt[p] = 1;
    }
    
    void build_AC () {
    	queue <int> q;
    	for(int i = 0;i < 4; ++i) {
    		if(t[0][i]) q.push(t[0][i]);
    	}
    	while(!q.empty()) {
    		int u = q.front();
    		q.pop();
    		for(int i = 0;i < 4; ++i) {
    			if(!t[u][i]) {
    				t[u][i] = t[fl[u]][i];
    			}
    			else {
    				fl[t[u][i]] = t[fl[u]][i];
    				q.push(t[u][i]);
    				cnt[t[u][i]] |= cnt[fl[t[u][i]]];
    			}
    		}
    	}
    }
    int cas;
    int main () {
    	while(~scanf("%d",&n) and n) {
    		memset(t,0,sizeof t);
    		memset(cnt,0,sizeof cnt);
    		memset(fl,0,sizeof fl);
    		idx = 0;
    		for(int i = 1;i <= n; ++i) {
    			scanf("%s",s);
    			insert(s);
    		}
    		//cout << 1 << endl;
    		build_AC();
    		//c/out << 1 << endl;
    		scanf("%s",s + 1);
    		int len = strlen(s + 1);
    		memset(f,0x3f,sizeof f);
    		f[0][0] = 0;
    		for(int i = 1;i <= len; ++i) {
    			for(int j = 0;j <= idx; ++j) {
    				for(int k = 0;k < 4; ++k) {
    					int ok = check(s[i]) != k;
    					int p = t[j][k];
    					if(!cnt[p]) {
    						f[i][p] = min(f[i][p],f[i - 1][j] + ok);
    					}
    					
    				}
    			}
    		}
    		int ans = 0x3f3f3f3f;
    		for(int i = 0;i <= idx; ++i) {
    			ans = min(ans,f[len][i]);
    		}
    		if(ans > 0x3f3f3f3f / 2) ans = -1;
    		printf("Case %d: %d\n",++cas,ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    leetcode 268. Missing Number
    DBSCAN
    python二维数组初始化
    leetcode 661. Image Smoother
    leetcode 599. Minimum Index Sum of Two Lists
    Python中的sort() key含义
    leetcode 447. Number of Boomerangs
    leetcode 697. Degree of an Array
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月3日)
    北京Uber优步司机奖励政策(1月2日)
  • 原文地址:https://www.cnblogs.com/akoasm/p/15168398.html
Copyright © 2011-2022 走看看