题目大意:

要求构造一个串,使得这个串是由所给的串相连接构成,连接能够有重叠的部分。

思路分析:

首先用所给的串建立自己主动机,每一个单词节点记录当前节点可以达到的最长后缀。

開始的时候想的是dp[i][j]表示长度为i,走到自己主动机的j节点的答案。

可是显然既然是能够反复覆盖的,那么每个节点的dp值都并非最优的。由于能够从一个地方截断去连接另外一个串。

所以正确姿势就是dp [i] [j] [k] 表示构造到了长度为 i 的串, 如今这个串后面有k 个字符是没有找到有效的节点的,然后在自己主动机上走到了j。

那么转移的时候,就有两种情况。

isword >= k+1。

。。

为什么是k+1 由于我们如今是去找的儿子节点,已经加1了。这种话就是这个节点能够全然覆盖没有匹配到的k个。换句话说就是让后面的k个字符找到了合法节点去匹配。那么就转移到dp [i+1] [j->next] [0]...

否则,假设k+1<=10 那么就让后面这个继续失配,那么久直接转移到 dp [i+1][j->next][k+1]...

最后累加答案。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int mod = 1000000009;
const char tab = 'a';
const int max_next = 4;
int rev[256];
struct trie
{
struct trie *fail;
struct trie *next[max_next];
int isword;
int index;
};
struct AC
{
trie *que[100005],*root,ac[100005];
int head,tail;
int idx;
trie *New()
{
trie *temp=&ac[idx];
for(int i=0;i<max_next;i++)temp->next[i]=NULL;
temp->fail=NULL;
temp->isword=0;
temp->index=idx++;
return temp;
}
void init()
{
idx=0;
root=New();
}
void Insert(trie *root,char *word,int len){
trie *t=root;
for(int i=0;i<len;i++){
if(t->next[rev[word[i]]]==NULL)
t->next[rev[word[i]]]=New();
t=t->next[rev[word[i]]];
}
t->isword=len;
}
void acbuild(trie *root){
int head=0,tail=0;
que[tail++]=root;
root->fail=NULL;
while(head<tail){
trie *temp=que[head++],*p;
for(int i=0;i<max_next;i++){
if(temp->next[i]){
if(temp==root)temp->next[i]->fail=root;
else {
p=temp->fail;
while(p!=NULL){
if(p->next[i]){
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL)temp->next[i]->fail=root;
}
if(temp->next[i]->fail->isword)
temp->next[i]->isword=max(temp->next[i]->isword,temp->next[i]->fail->isword);
que[tail++]=temp->next[i];
}
else if(temp==root)temp->next[i]=root;
else temp->next[i]=temp->fail->next[i];
}
}
}
void tra()
{
for(int i=0;i<idx;i++)
{
if(ac[i].fail!=NULL)printf("fail = %d ",ac[i].fail->index);
for(int k=0;k<max_next;k++)
printf("%d ",ac[i].next[k]->index);
puts("");
}
}
}sa,sb;
string cq[55];
char word[55];
int dp[1005][105][11];
void add(int &a,int b)
{
a+=b;
if(a>=mod)a-=mod;
}
int solve(int L)
{
memset(dp,0,sizeof dp);
dp[0][0][0]=1;
for(int i=0;i<L;i++)
{
for(int j=0;j<sa.idx;j++)
{
for(int k=0;k<10;k++)
{
for(int d=0;d<4;d++)
{
if(sa.ac[j].next[d]->isword>=k+1)
add(dp[i+1][sa.ac[j].next[d]->index][0],dp[i][j][k]);
else if(k+1<=10)
add(dp[i+1][sa.ac[j].next[d]->index][k+1],dp[i][j][k]);
}
}
}
}
int ans=0;
for(int i=0;i<sa.idx;i++)
{
add(ans,dp[L][i][0]);
}
return ans;
} int main()
{
rev['A']=0;
rev['C']=1;
rev['G']=2;
rev['T']=3;
int m,L;
while(cin>>L>>m)
{
sa.init();
for(int i=1;i<=m;i++)
{
cin>>word;
sa.Insert(sa.root,word,strlen(word));
}
sa.acbuild(sa.root);
printf("%d\n",solve(L));
}
return 0;
}

Codeforces 86C Genetic engineering (AC自己主动机+dp)的更多相关文章

  1. hdu4758 Walk Through Squares (AC自己主动机+DP)

    Walk Through Squares Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others ...

  2. HDU - 4758 Walk Through Squares (AC自己主动机+DP)

    Description   On the beaming day of 60th anniversary of NJUST, as a military college which was Secon ...

  3. POJ 2778 DNA Sequence (AC自己主动机 + dp)

    DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...

  4. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

  5. Hdu 3341 Lost&#39;s revenge (ac+自己主动机dp+hash)

    标题效果: 举个很多种DNA弦,每个字符串值值至1.最后,一个长字符串.要安排你最后一次另一个字符串,使其没事子值和最大. IDEAS: 首先easy我们的想法是想搜索的!管她3721..直接一个字符 ...

  6. poj 3691 DNA repair(AC自己主动机+dp)

    DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5877   Accepted: 2760 Descri ...

  7. hdu4057 Rescue the Rabbit(AC自己主动机+DP)

    Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  8. Zoj 3535 Gao the String II (AC自己主动机+dp)

    题目大意: 用集合A中的串构造出一个串,使之让很多其它的setB中的串成为他的子串. 思路分析: 和 Codeforces 86C 几乎相同. 只是这里是要用A中的构造. 先用A 和 B的串构造一个自 ...

  9. HDU - 4511 小明系列故事――女友的考验(AC自己主动机+DP)

    Description 最终放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候.女朋友告诉他.她在电影院等他,小明过来的路线必须满足给定的规则:  1.如果小明 ...

随机推荐

  1. AS3的反编译

    一个as3写的swf反编译,修改类库: http://www.swfwire.com/ http://www.swfwire.com/decompiler 基于此类库的swf反编译工具(air) ht ...

  2. 吐槽一下Page Restore

    以前觉得Page Restore确实挺好用的,而且确实用Page Restore快速解决过一些问题.但是仔细想想很多时候Page Restore可能根本用不上. 因为SQL Server在备份的时候是 ...

  3. Linux中-POSIX 线程详解

    一种支持内存共享的简捷工具   摘自https://www.ibm.com/developerworks/cn/linux/thread/posix_thread1/ 线程是有趣的 了解如何正确运用线 ...

  4. PHP $_POST

    $_POST 变量用于收集来自 method="post" 的表单中的值. $_POST 变量 $_POST 变量是一个数组,内容是由 HTTP POST 方法发送的变量名称和值. ...

  5. JavaWeb get请求乱码处理

      乱码终极解决方案 Author:Marydon 一.安装好eclipse/myeclipse后,先将开发环境改成UTF-8; 更改工作空间编码方式 window-->preferences- ...

  6. Redis学习(5)-Jedis(Java操作redis数据库技术)

    Java连接redis 一,导入jar包 Redis有什么命令,Jedis就有什么方法 设置防火墙 在Linux上面运行如下代码: 单实例:Jedis实例: package com.jedis.dem ...

  7. 解决windows下MySQL表名大写自动变小写的问题

    解决windows下MySQL表名大写自动变小写的问题   有些人可能会遇到在windows下,表名不能用大写字母, 即使使用了大写字母的建表语句,还是会被自动转成小写.   解决方法:  打开 My ...

  8. 转:【HTTP】常见错误码说明

    一些常见的状态码为: 200 - 服务器成功返回网页404 - 请求的网页不存在503 - 服务不可用详细分解: 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明100 ...

  9. Swift代理造成内存泄漏的解决办法

    在swift中,使用代理 ,可能很多人会这样实现: .首先定义一份协议. protocol ToolProrocol{ //代理方法 func didRecieveResults(result:Int ...

  10. HDUOJ-------1753大明A+B(大数之小数加法)

    大明A+B Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...