zoukankan      html  css  js  c++  java
  • L

    Lost and AekdyCoin are friends. They always play "number game"(A boring game based on number theory) together. We all know that AekdyCoin is the man called "nuclear weapon of FZU,descendant of Jingrun", because of his talent in the field of number theory. So Lost had never won the game. He was so ashamed and angry, but he didn't know how to improve his level of number theory.

    One noon, when Lost was lying on the bed, the Spring Brother poster on the wall(Lost is a believer of Spring Brother) said hello to him! Spring Brother said, "I'm Spring Brother, and I saw AekdyCoin shames you again and again. I can't bear my believers were being bullied. Now, I give you a chance to rearrange your gene sequences to defeat AekdyCoin!".

    It's soooo crazy and unbelievable to rearrange the gene sequences, but Lost has no choice. He knows some genes called "number theory gene" will affect one "level of number theory". And two of the same kind of gene in different position in the gene sequences will affect two "level of number theory", even though they overlap each other. There is nothing but revenge in his mind. So he needs you help to calculate the most "level of number theory" after rearrangement.
    Input
    There are less than 30 testcases.
    For each testcase, first line is number of "number theory gene" N(1<=N<=50). N=0 denotes the end of the input file.
    Next N lines means the "number theory gene", and the length of every "number theory gene" is no more than 10.
    The last line is Lost's gene sequences, its length is also less or equal 40.
    All genes and gene sequences are only contains capital letter ACGT.
    Output
    For each testcase, output the case number(start with 1) and the most "level of number theory" with format like the sample output.
    Sample Input
    3
    AC
    CG
    GT
    CGAT
    1
    AA
    AAA
    0
    Sample Output
    Case 1: 3
    Case 2: 2

    题意:把给定的文本串重排,使得每个模式串在文本串中出现的次数和最大。串与串之间可重叠。

    思路:很明显要AC自动机处理模式串,然后由于每个字符的数量是固定的,所以要记忆化搜索,但是正常开数组的话,数组的大小为500 * 40 * 40 * 40,显然会 MLE,所以采用变进制法代表每个状态,设num0, num1, num2, num3 为字符 A, T, C, G的数量, c0, c1, c2, c3为当前状态字符A, T, C, G 的数量,那么状态state = c0 * (num1 + 1) * (num2 + 1) * (num3 + 1) + c1 * (num2 + 1) * (num3 + 1) + c2 * (num3 + 1) + c3;

    注意:题目没说模式串各不相同,所以插入的时候要Exits[p]++ 而不是 Exits[p] = 1;

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <string>
    #include <string.h>
    #include <map>
    #include <iostream>
    using namespace std;
    const int maxn = 550;
    const int mod = 20090717;
    int INF = 1e9;
    int nex[maxn][4], Exits[maxn], fail[maxn], last[maxn], cnt;
    int num0, num1, num2, num3;
    char t[maxn];
    int n, m;
    int getId(char ch){
    	if(ch == 'A') return 0;
    	else if(ch == 'T') return 1;
    	else if(ch == 'C') return 2;
    	else return 3;
    }
    void insert(char *s, int len){
    	int p = 0;
    	for(int i = 0; i < len; i++){
    		int x = getId(s[i]);
    		if(nex[p][x] == 0){
    			memset(nex[cnt], 0, sizeof(nex[cnt]));
    			Exits[cnt] = 0;
    			last[cnt] = 0;
    			fail[cnt] = 0;
    			nex[p][x] = cnt++;
    		}
    		p = nex[p][x];
    	}
    	Exits[p]++;
    } 
    
    queue<int> que;
    void Build(){
    	for(int i = 0; i < 4; i++){
    		if(nex[0][i]) que.push(nex[0][i]);
    	}
    	while(que.size()){
    		int p = que.front();
    		que.pop();
    		Exits[p] += Exits[fail[p]];
    		for(int i = 0; i < 4; i++){
    			int u = nex[p][i];
    			if(u){
    				fail[u] = nex[fail[p]][i];
    				last[u] = Exits[fail[u]] ? fail[u] : last[fail[u]];
    				que.push(u);
    			} else {
    				nex[p][i] = nex[fail[p]][i];
    			}
    		}
    	}
    }
    
    int getState(int c0, int c1, int c2, int c3){
    	return c0 * (num1 + 1) * (num2 + 1) * (num3 + 1) + c1 * (num2 + 1) * (num3 + 1) + c2 * (num3 + 1) + c3;
    }
    int dp[505][15005];
    int dfs(int st, int c0, int c1, int c2, int c3){
    	int state = getState(c0, c1, c2, c3);
    	if(dp[st][state] != -1) return dp[st][state];
    	int ans = 0;
    	if(c0){
    		int u = nex[st][0];
    		ans = max(ans, dfs(u, c0 - 1, c1, c2, c3) + Exits[u]);
    	}
    	if(c1){
    		int u = nex[st][1];
    		ans = max(ans, dfs(u, c0, c1 - 1, c2, c3) + Exits[u]);
    	}
    	if(c2){
    		int u = nex[st][2];
    		ans = max(ans, dfs(u, c0, c1, c2 - 1, c3) + Exits[u]);
    	}
    	if(c3){
    		int u = nex[st][3];
    		ans = max(ans, dfs(u, c0, c1, c2, c3 - 1) + Exits[u]);
    	}
    	dp[st][state] = ans;
    	return ans;
    }
    int main(int argc, char const *argv[])
    {
    	int ca = 0;
    	while(1){
    		scanf("%d", &n);
    		if(n == 0) break;
    		cnt = 1;
    		memset(nex[0], 0, sizeof(nex[0]));
    		num0 = num1 = num2 = num3 = 0;
    		for(int i = 1; i <= n; i++){
    			char s[25];
    			scanf("%s", s);
    			insert(s, strlen(s));
    		}
    		scanf("%s", t);
    		int len = strlen(t);
    		for(int i = 0; i < len; i++){
    			if(getId(t[i]) == 0) num0++;
    			else if(getId(t[i]) == 1) num1++;
    			else if(getId(t[i]) == 2) num2++;
    			else num3++;
    		}
    		Build();
    		memset(dp, -1, sizeof(dp));
    		int ans = dfs(0, num0, num1, num2, num3);
    		printf("Case %d: %d
    ", ++ca, ans);
    	}
    
        return 0;
    }
    
    
    
  • 相关阅读:
    在jsp页面如果运行时路径错误解决方法
    Maven实现ssm框架整合
    JS进阶(二)this指南——绑定了谁?
    防御性编程方法收集
    react将多个公共组件归成一类,方便调用
    初始化构建React+Ts项目时出现:Module build failed (from ./node_modules/css-loader/dist/cjs.js): CssSyntaxError
    Dva三种方式实现dispatch的Promise回调
    ES6多层解构
    ES6解构过程添加一个默认值和赋值一个新的值
    Antd-Pro2.0版本如何修改代理,让Mock变为真实服务器接口
  • 原文地址:https://www.cnblogs.com/PCCCCC/p/13260113.html
Copyright © 2011-2022 走看看