Codeforces 86C Genetic engineering (AC自己主动机+dp)
题目大意:
要求构造一个串,使得这个串是由所给的串相连接构成,连接能够有重叠的部分。
思路分析:
首先用所给的串建立自己主动机,每一个单词节点记录当前节点可以达到的最长后缀。
開始的时候想的是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)的更多相关文章
- hdu4758 Walk Through Squares (AC自己主动机+DP)
Walk Through Squares Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others ...
- HDU - 4758 Walk Through Squares (AC自己主动机+DP)
Description On the beaming day of 60th anniversary of NJUST, as a military college which was Secon ...
- POJ 2778 DNA Sequence (AC自己主动机 + dp)
DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...
- HDU - 2825 Wireless Password(AC自己主动机+DP)
Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...
- Hdu 3341 Lost's revenge (ac+自己主动机dp+hash)
标题效果: 举个很多种DNA弦,每个字符串值值至1.最后,一个长字符串.要安排你最后一次另一个字符串,使其没事子值和最大. IDEAS: 首先easy我们的想法是想搜索的!管她3721..直接一个字符 ...
- poj 3691 DNA repair(AC自己主动机+dp)
DNA repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 5877 Accepted: 2760 Descri ...
- hdu4057 Rescue the Rabbit(AC自己主动机+DP)
Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- Zoj 3535 Gao the String II (AC自己主动机+dp)
题目大意: 用集合A中的串构造出一个串,使之让很多其它的setB中的串成为他的子串. 思路分析: 和 Codeforces 86C 几乎相同. 只是这里是要用A中的构造. 先用A 和 B的串构造一个自 ...
- HDU - 4511 小明系列故事――女友的考验(AC自己主动机+DP)
Description 最终放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候.女朋友告诉他.她在电影院等他,小明过来的路线必须满足给定的规则: 1.如果小明 ...
随机推荐
- 在Fedora8上安装使用ActiveMQ5.8
[ActiveMQ安装] ActiveMQ在win平台的安装简单,在Linux Fedora上安装也不难,解压就可以了.以下是我总结的步骤: 第一步,从以下地址下载apache-activemq-5. ...
- 【问题&解决】还原数据库提示“介质集有2个介质簇,但只提供了1个。必须提供所有成员”的解决办法
今天在对数据库备份与还原的过程中,我遇到一个问题“介质集有2个介质簇,但只提供了1个.必须提供所有成员”,下面详细的介绍一下遇到问题的经过与问题解决的方法! 一.备份与还原遇到的问题描述与解决方法: ...
- C# 单元测试几个方法的用法
单元测试的基本方法是调用被测代码的函数,输入函数的参数值,获取返回结果,然后与预期测试结果进行比较,如果相等则认为测试通过,否则认为测试不通过. 1.Assert类的使用 Assert.Inconcl ...
- UILabel字体间距调整
思路: 写一个 UILbel的子类:在子类里面重新布置UILbel的字体间距: 如代码 .h #import <UIKit/UIKit.h> @interface AdjustableUI ...
- Oracle体系结构三(学习笔记)
- MySQL 导出函数与存储过程
C:\Users\yan>mysqldump -u用户 -p -n -t -d -R 数据库 > .sql Enter password: ******** C:\Users\yan> ...
- mysql 创建表单
1.表名:Customer 属性: ID 字符型 最大10个字符 ——顾客编号 NAME 字符型 最大16个字符 ——顾客姓名 SEX 字符型 最大2个字符 ——性别 ...
- element-ui 源码架构
1.项目结构 2.src下的入口文件 https://github.com/ElemeFE/element/blob/dev/src/index.js 入口文件实现的功能为: (1)国际化配置 (2) ...
- List(T)类的方法
List<T>.Clear 方法 List<T>.RemoveAll 方法 http://msdn.microsoft.com/zh-cn/library/s6hkc2c4(v ...
- heap与stack的差
本文内容来源于<程序猿面试宝典>第三版. 在进行C/C++编程时.常常将操作的内存分下面几个类别: 栈区(stack):由编译器自己主动分配和释放,存放函数的參数值.局部变量的值等. 其操 ...