题目大意:

用集合A中的串构造出一个串,使之让很多其它的setB中的串成为他的子串。

思路分析:

Codeforces 86C 几乎相同。

只是这里是要用A中的构造。

先用A 和 B的串构造一个自己主动机。然后对于A集合的尾结点给出一个最大后缀匹配,对于B集合的尾结点给一个权值。

dp[i][j][k] 表示已经构造出来了一个长度为i的串,如今走到了自己主动机的j结点。i长度后面有k个字符是没有匹配到的。

继续在自己主动机上走进行状态转移。

if(isword >= k +1 )dp [i+1] [j->next[d] ][0] = max(dp [i+1] [ j->next[d] ][0] , dp[i][j][k] + j->next[d]->val)...

else if( k+1 <= 10) dp [i+1] [j->next[d] ] [k+1 ] = max (dp[i+1][ j->next[d] ] [k+1] , dp [i][j][k] + j->next[d]->val)

...

#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 = 26;
int rev[256];
struct trie
{
struct trie *fail;
struct trie *next[max_next];
int isword,tip;
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++;
temp->tip=0;
return temp;
}
void init()
{
idx=0;
root=New();
}
void Insert(trie *root,char *word,int len,int cmd){
trie *t=root;
for(int i=0;i<len;i++){
if(t->next[word[i]-tab]==NULL)
t->next[word[i]-tab]=New();
t=t->next[word[i]-tab];
}
if(cmd)t->isword=len;
else t->tip++;
}
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);
temp->next[i]->tip+=temp->next[i]->fail->tip;
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;
char word[55];
int dp[65][1005][11]; int solve(int L)
{
memset(dp,-1,sizeof dp);
dp[0][0][0]=0;
for(int i=0;i<L;i++)
{
for(int j=0;j<sa.idx;j++)
{
for(int k=0;k<10;k++)
{
if(dp[i][j][k]<0)continue;
for(int d=0;d<4;d++)
{
if(sa.ac[j].next[d]->isword>=k+1)
dp[i+1][sa.ac[j].next[d]->index][0]=max(dp[i+1][sa.ac[j].next[d]->index][0],dp[i][j][k]+sa.ac[j].next[d]->tip);
else if(k+1<=10)
dp[i+1][sa.ac[j].next[d]->index][k+1]=max(dp[i+1][sa.ac[j].next[d]->index][k+1],dp[i][j][k]+sa.ac[j].next[d]->tip);
}
}
}
}
int ans=0;
for(int l=1;l<=L;l++)
for(int i=0;i<sa.idx;i++)
ans=max(ans,dp[l][i][0]);
return ans;
} int main()
{
rev['A']=0;
rev['C']=1;
rev['G']=2;
rev['T']=3;
int m,L,n;
while(cin>>m>>n>>L)
{
sa.init();
for(int i=1;i<=m;i++)
{
cin>>word;
sa.Insert(sa.root,word,strlen(word),1);
}
for(int i=1;i<=n;i++)
{
cin>>word;
sa.Insert(sa.root,word,strlen(word),0);
}
sa.acbuild(sa.root);
printf("%d\n",solve(L));
}
return 0;
}

Zoj 3535 Gao the String II (AC自己主动机+dp)的更多相关文章

  1. ZOJ 3228 Searching the String (AC自己主动机)

    题目链接:Searching the String 解析:给一个长串.给n个不同种类的短串.问分别在能重叠下或者不能重叠下短串在长串中出现的次数. 能重叠的已经是最简单的AC自己主动机模板题了. 不能 ...

  2. zoj 3430 Detect the Virus(AC自己主动机)

    Detect the Virus Time Limit: 2 Seconds      Memory Limit: 65536 KB One day, Nobita found that his co ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【转】linux之type命令

    转自: http://codingstandards.iteye.com/blog/831504 用途说明 type命令用来显示指定命令的类型.一个命令的类型可以是如下之一 alias 别名 keyw ...

  2. UE4 集成讯飞听写插件

    搞了几天,有些坑记录一下. 3个方面的知识需要学习 1.制作UE4插件 2.引入第三方库 3.讯飞听写的api 一看是参考 https://blog.csdn.net/u012793104/artic ...

  3. 努比亚(nubia) Z18 mini NX611J 解锁BootLoader 并刷入recovery ROOT

    努比亚(nubia)  Z18 mini NX611J解锁BootLoader 并刷入recovery ROOT 工具下载链接:https://pan.baidu.com/s/1toU-mTR9FNE ...

  4. SQL基本操作——JOIN多表联查

    基本概念 join :用于根据两个或多个表中的列之间的关系,从这些表中查询数据. join和key:有时为了得到完整的结果,我们需要从两个或更多的表中获取结果.我们就需要执行 join.数据库中的表可 ...

  5. 一款批量linux管理工具batchshell

    BatchShell是什么? BatchShell是一款基于SSH2的批量文件传输及命令执行工具,它可以同时传输文件到多台远程服务器以及同时对多台远程服务器执行命令.BatchShell基于原生的sh ...

  6. ImageMagick的下载和配置

    2. 新建一个VC++的工程,项目->属性 VC++目录中 包含目录中加入4项,ImageMagick安装路径下的include文件夹,和include里边的三个文件夹. 库目录中加入1项,Im ...

  7. UGUI世界坐标转换为UI本地坐标(游戏Hud的实现)

    实现世界坐标的原理是: 世界坐标和UGUI的坐标分属两个坐标系,他们之间是无法进行转换的,需要通过屏幕坐标系来进行转换(因为屏幕坐标是固定的),即先将游戏场景中的世界坐标通过游戏场景Camera转化为 ...

  8. 1 JSONP

    一.什么是跨域访问举个栗子:在A网站中,我们希望使用Ajax来获得B网站中的特定内容.如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题.你可以理解为两个域名之间不能跨过域名来发送请求或者请求 ...

  9. ESP、EBP、CALL 指令与局部变量浅析

    概述 函数调用是计算机程序中一个最重要的概念之一,从汇编的角度看,能更加直观地理解函数调用的原理,理解 CALL 指令调用过程中 ESP.EBP 寄存器的作用. 我们先从一段简陋的 C 语言代码说起, ...

  10. 阅读《JavaScript设计模式》第一章心得

    1.明白自己 明白了自己写的代码为什么难懂且臃肿,不方便阅读且效率低.最主要的是为什么整套流程下来只能我一个人写,因为这样的代码根本没有团队力,协同能力差.对js理解的不过透彻. 2.真正的学会对象与 ...