标题效果:

构造一个字符串,使得有两个和两个以上的目标串。长短L这一系列有多少串都。

IDEAS:

只有全款减有1一些字符串,没有目标就是答案。

假定数据是非常小的,够用dp解。dp[i][j][k] 表示长度为i,走到自己主动机的j。有k个目标串的数量。

转移便是。

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

else dp[i+1][j->next][0]+=dp[i][j][0],dp[i+1][j->next][1] += dp[i][j][1]...

如今长度达到百万。

所以用矩阵优化。

设自己主动机的节点数量为idx,那么就开一个(2*idx。2*idx)的矩阵。

假设i<idx j<idx 表示 開始在i的时候没有目标串,走到j也没有。

假设i<idx j>idx 表示 開始在i的时候没有目标串。走到j有了一个。

后面同理。

。。

那么构造这个矩阵便是依照上面的dp方程类似构造。

if(j->next[d]->isword)matrix [i][j->next->index+idx]++; 開始的时候没有,走过来加一个

else matrix [i][j]++,matrix [i+idx][j+idx] 開始的时候没有,走到j也没有  和  開始的时候有一个,走到j还是一个。

矩阵的构造是难= =

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 75
using namespace std; const int mod = 10007;
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++;
}
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++;
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; struct matrix
{
int r,c;
int data[N][N];
matrix(){}
matrix(int _r,int _c):r(_r),c(_c){memset(data,0,sizeof data);}
friend matrix operator * (const matrix A,const matrix B)
{
matrix res;
res.r=A.r;res.c=B.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)
{
for(int j=0;j<B.c;j++)
{
for(int k=0;k<A.c;k++)
{
if(A.data[i][k] && B.data[k][j]){
res.data[i][j]+=A.data[i][k]*B.data[k][j];
res.data[i][j]%=mod;
}
}
}
}
return res;
}
friend matrix operator + (const matrix A,const matrix B)
{
matrix res;
res.r=A.r;res.c=A.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)
{
for(int j=0;j<A.c;j++)
{
res.data[i][j]=A.data[i][j]+B.data[i][j];
res.data[i][j]%=mod;
}
}
return res;
}
friend matrix operator - (const matrix A,const matrix B)
{
matrix res;
res.r=A.r;res.c=A.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)
{
for(int j=0;j<A.c;j++)
{
res.data[i][j]=A.data[i][j]-B.data[i][j];
res.data[i][j]=(res.data[i][j]%mod+mod)%mod;
}
}
return res;
}
friend matrix operator ^ (matrix A,int n)
{
matrix res;
res.r=A.r;res.c=A.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)res.data[i][i]=1; while(n)
{
if(n&1)res=res*A;
A=A*A;
n>>=1;
}
return res;
}
void print()
{
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
printf("%d ",data[i][j]);
puts("");
}
}
}E,zero; char word[30]; int main()
{
rev['A']=0;
rev['C']=1;
rev['G']=2;
rev['T']=3;
int n,L;
while(scanf("%d%d",&n,&L)!=EOF)
{
sa.init();
for(int i=1;i<=n;i++)
{
scanf("%s",word);
sa.Insert(sa.root,word,strlen(word));
}
sa.acbuild(sa.root);
E=matrix(sa.idx*2,sa.idx*2); for(int i=0;i<sa.idx*2;i++)E.data[i][i]=1; matrix origin=matrix(sa.idx*2,sa.idx*2); for(int i=0;i<sa.idx;i++)
{
for(int j=0;j<4;j++)
{
int temp=sa.ac[i].next[j]->index;
if(sa.ac[i].next[j]->isword)
origin.data[i][temp+sa.idx]++;
else
origin.data[i][temp]++,origin.data[i+sa.idx][temp+sa.idx]++;
}
}
origin.print(); origin=origin^L; int ans=1;
int x=4;
int t=L;
while(t)
{
if(t&1)ans=(ans*x)%mod;
x=(x*x)%mod;
t>>=1;
}
for(int i=0;i<2*sa.idx;i++)
{
ans-=origin.data[0][i];
ans=(ans+mod)%mod;
} printf("%d\n",ans);
}
return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

Hdu 3962 Microgene (AC自己主动机+矩阵)的更多相关文章

  1. poj 2778 AC自己主动机 + 矩阵高速幂

    // poj 2778 AC自己主动机 + 矩阵高速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自 ...

  2. Hdu 2243 考研路茫茫——单词情结 (AC自己主动机+矩阵)

    哎哟喂.中文题. . .不说题意了. 首先做过POJ 2778能够知道AC自己主动机是能够求出长度为L的串中不含病毒串的数量的. POJ 2778的大概思路就是先用全部给的病毒串建一个AC自己主动机. ...

  3. hdu 2243 考研绝望——复杂的文字(AC自己主动机+矩阵高速功率)

    pid=2243" target="_blank" style="">题目链接:hdu 2243 考研路茫茫--单词情结 题目大意:略. 解题思 ...

  4. POJ 2778 AC自己主动机+矩阵幂 不错的题

    http://poj.org/problem?id=2778 有空再又一次做下,对状态图的理解非常重要 题解: http://blog.csdn.net/morgan_xww/article/deta ...

  5. POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)

    http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...

  6. hdu 4057 AC自己主动机+状态压缩dp

    http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...

  7. HDU 2825 Wireless Password (AC自己主动机,DP)

    pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...

  8. HDU 2896 病毒侵袭 (AC自己主动机)

    pid=2896">http://acm.hdu.edu.cn/showproblem.php?pid=2896 病毒侵袭 Time Limit: 2000/1000 MS (Java ...

  9. [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem

    意甲冠军: 给n快报,和m频率. 然后进入n字母出现的概率 然后给目标字符串str 然后问m概率倍的目标字符串是敲数量. 思维: AC自己主动机+可能性dp简单的问题. 首先建立trie图,然后就是状 ...

随机推荐

  1. wcf例子01

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  2. 【原创】编写多线程Python爬虫来过滤八戒网上的发布任务

    目标: 以特定语言技术为关键字,爬取八戒网中网站设计开发栏目下发布的任务相关信息 需求: 用户通过设置自己感兴趣的关键字或正则表达式,来过滤信息. 我自己选择的是通过特定语言技术作为关键字,php.j ...

  3. bash组织成树数据结构

    君子也非独占,善假于物!bash也因此.昨天晚上,今天早上世界杯很精彩.晚上醒来看到不断地居住的电话.早上没有喝的水开始赞赏在英国和意大利的对决.也TM精彩,最后生下了罗马文化.意大利伊特鲁里亚文化获 ...

  4. 剖析html对标准标签和自定义标签闭合与不闭合渲染问题

    昨天在修改去年写的系统的时候无意中看到了当时写的一个利用标准标签未闭合在单元格内把整个单元格颜色渲染成红色的效果,如下: 当时的问题是从后台返回来的是个int整数而%是写在页面上的如图 这 时候就出现 ...

  5. UVA 1411 - Ants(二分图完美匹配)

    UVA 1411 - Ants 题目链接 题意:给定一些黑点白点,要求一个黑点连接一个白点,而且全部线段都不相交 思路:二分图完美匹配,权值存负的欧几里得距离,这种话,相交肯定比不相交权值小,所以做一 ...

  6. [LeetCode299]Bulls and Cows

    题目: You are playing the following Bulls and Cows game with your friend: You write down a number and ...

  7. 左右10g DG中间ORA-19527和ORA-00312错误解决演示示例

    这些天大厦10g DG Windows 2008 R2测试环境,主要明天去给客户端,再建一个生产资源库DG,其中一些发现的问题.特此记录下来 因为将要部署到生产环境.所以考虑在线搭建DG的方案,即不停 ...

  8. 采用UltraISO制作U菜Win7安装盘,显现&quot;File not find /BOOT/CDMENU.EZB.ezb&quot;错误

    一机公司Win7动力password不知道.这台机器也很慢, 刷新Win7,运用32位Ghost设备ISO档.从机U之后启动盘,演出 "File not find /BOOT/CDMENU. ...

  9. 无尽的循环ViewPager

    现在的情况 不改变的源代码,什么时候ViewPager滑动到最后item的时候,他就无法再往右滑动:当ViewPager滑动到第一个item的时候,他也无法再往前滑动. (以上全是废话) 设想 我们能 ...

  10. KVO 其原理探究

    什么是KVO ? KVO这是Key-Value Observing,它提供了一种机制,指定的对象的属性被改动后,则对象就会接受到通知. 简单的说就是每次指定的被观察的对象的属性被改动后.KVO就会自己 ...