poj 2778 ,spoj1676

感谢http://blog.henix.info/blog/poj-2778-aho-corasick-dp.html给的灵感

 

看数据规模,很容易想到用矩阵求解,关键是如何得到原始矩阵。上面连接博客中的方法给力,在AC自动机上确定出每一个点的跳转点,即jump数组,表示该点可以跳转到的点。

利用每个点的jump数组,我们就可以确定出一张跳转表,也即时我们需要的原始矩阵。

对每个点,如果它不是病毒片段的结尾,那么它便是安全的。我们很容易可以理解,安全点到安全点之间的跳转,总是安全的。给每个安全点一个编号,构建一个矩阵a[][]。

那么a[i][j]就表示从第j个安全点能够跳转到第i个安全点的数量。将这个矩阵开k次方,取第一列中的所有项之和,就是答案了。

View Code
  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 using namespace std;
  5 #define mod 100000
  6 
  7 struct node
  8 {
  9     struct node *fail;
 10     struct node *next[4];
 11     struct node *jump[4];
 12     int cnt;
 13 };
 14 
 15 node root[110];
 16 int num;
 17 int n,m;
 18 char str[11];
 19 
 20 int get_index(char c)
 21 {
 22     if(c=='A')
 23         return 0;
 24     if(c=='C')
 25         return 1;
 26     if(c=='T')
 27         return 2;
 28     return 3;
 29 }
 30 
 31 void insert(char word[])
 32 {
 33     int i=0;
 34     struct node *tmp=root;
 35     while(word[i])
 36     {
 37         int b=get_index(word[i]);
 38         if(tmp->next[b]==NULL)
 39         {
 40             memset(root+num,0,sizeof(struct node));
 41             tmp->next[b]=root+num;
 42             num++;
 43         }
 44         tmp=tmp->next[b];
 45         i++;
 46     }
 47     tmp->cnt++;
 48 }
 49 
 50 node *q[110];
 51 int head,tail;
 52 
 53 void add_Fail()
 54 {
 55     head=tail=0;
 56     q[tail++]=root;
 57     while(head<tail)
 58     {
 59         node *x=q[head++];
 60         int i;
 61         for(i=0;i<4;i++)
 62         {
 63             node *t=x->fail;
 64             while(t!=NULL && t->next[i]==NULL)
 65                 t=t->fail;
 66             if(x->next[i]!=NULL)
 67             {
 68                 q[tail++]=x->next[i];
 69                 if(t==NULL)
 70                     x->next[i]->fail=root;
 71                 else
 72                 {
 73                     x->next[i]->fail=t->next[i];
 74                     if(t->next[i]->cnt>0)
 75                         x->next[i]->cnt=1;
 76                 }
 77                 x->jump[i]=x->next[i];
 78             }
 79             else
 80             {
 81                 if(t==NULL)
 82                     x->jump[i]=root;
 83                 else
 84                     x->jump[i]=t->next[i];
 85             }
 86         }
 87     }
 88 }
 89 
 90 struct MAT
 91 {
 92     int a[110][110];
 93 };
 94 
 95 int len;
 96 
 97 MAT getE()
 98 {
 99     MAT ans;
100     int i,j;
101     for(i=0;i<len;i++)
102         for(j=0;j<len;j++)
103             ans.a[i][j]=0;
104     for(i=0;i<len;i++)
105         ans.a[i][i]=1;
106     return ans;
107 }
108 
109 MAT mulPow(MAT a,MAT b)
110 {
111     MAT ans;
112     int i,j,k;
113     for(i=0;i<len;i++)
114     {
115         for(j=0;j<len;j++)
116         {
117             __int64 sum=0;
118             for(k=0;k<len;k++)
119             {
120                 sum+=(__int64)a.a[i][k]*b.a[k][j];
121                 sum%=mod;
122             }
123             ans.a[i][j]=sum;
124         }
125     }
126     return ans;
127 }
128 
129 MAT solve(MAT a,int k)
130 {
131     MAT ans;
132     ans=getE();
133     while(k)
134     {
135         if(k&1)
136         {
137             ans=mulPow(ans,a);
138         }
139         a=mulPow(a,a);
140         k=k>>1;
141     }
142     return ans;
143 }
144 
145 int main()
146 {
147     int i,j,k;
148     MAT res;
149     //freopen("D:\\in.txt","r",stdin);
150     while(scanf("%d%d",&n,&m)==2)
151     {
152         num=1;
153         memset(root,0,sizeof(struct node));
154         for(i=0;i<n;i++)
155         {
156             scanf("%*c%s",str);
157             insert(str);
158         }
159         add_Fail();
160         int id=0,id1;
161         for(i=0;i<num;i++)
162         {
163             if(root[i].cnt==0)
164             {
165                 id1=0;
166                 for(j=0;j<num;j++)
167                 {
168                     if(root[j].cnt==0)
169                     {
170                         int count=0;
171                         for(k=0;k<4;k++)
172                         {
173                             if(root[j].jump[k]==root+i)
174                                 count++;
175                         }
176                         res.a[id][id1]=count;
177                         id1++;
178                     }
179                 }
180                 id++;
181             }
182         }
183         len=id;
184         res=solve(res,m);
185         int ans=0;
186         for(i=0;i<len;i++)
187         {
188             ans=(ans+res.a[i][0])%mod;
189             ans%=mod;
190         }
191         printf("%d\n",ans);
192     }
193     return 0;
194 }

 

spoj 1676 http://www.spoj.pl/problems/GEN/这个题和上面那个题大概意思是一样的。只不过这题数据规模大一些,上面的程序矩阵乘积的时候并没有对取模运算做任何判断,

对于矩阵连乘的问题,取模运算是消耗时间的大客户。这题只要对取模运算加上判断,尽量少用就可以过了,不然就是tle了。。。

View Code
  1 #include<iostream>
  2 #include<string>
  3 #include<stdio.h>
  4 #include<memory.h>
  5 using namespace std;
  6 #define mod 10007
  7 
  8 struct node
  9 {
 10     struct node *fail;
 11     struct node *next[26];
 12     struct node *jump[26];
 13     int cnt;
 14 };
 15 
 16 node root[61];
 17 int num;
 18 int n,m;
 19 char str[7];
 20 
 21 void insert(char word[])
 22 {
 23     int i=0;
 24     node *tmp=root;
 25     while(word[i])
 26     {
 27         int b=word[i]-'A';
 28         if(tmp->next[b]==NULL)
 29         {
 30             tmp->next[b]=root+num;
 31             memset(root+num,0,sizeof(struct node));
 32             num++;
 33         }
 34         tmp=tmp->next[b];
 35         i++;
 36     }
 37     tmp->cnt=1;
 38 }
 39 
 40 node *q[100];
 41 int head,tail;
 42 
 43 void add_Fail()
 44 {
 45     head=tail=0;
 46     q[tail++]=root;
 47     while(head<tail)
 48     {
 49         node *x=q[head++];
 50         for(int i=0;i<26;i++)
 51         {
 52             node *t=x->fail;
 53             while(t!=NULL && t->next[i]==NULL)
 54                 t=t->fail;
 55             if(x->next[i]!=NULL)
 56             {
 57                 q[tail++]=x->next[i];
 58                 if(t==NULL)
 59                     x->next[i]->fail=root;
 60                 else
 61                 {
 62                     x->next[i]->fail=t->next[i];
 63                     if(t->next[i]->cnt)
 64                         x->next[i]->cnt=1;
 65                 }
 66                 x->jump[i]=x->next[i];
 67             }
 68             else
 69             {
 70                 if(t!=NULL)
 71                     x->jump[i]=t->next[i];
 72                 else
 73                     x->jump[i]=root;
 74             }
 75         }
 76     }
 77 }
 78 
 79 struct Mat
 80 {
 81     int a[61][61];
 82 };
 83 Mat e;
 84 int len,all;
 85 
 86 Mat mulPow(Mat a,Mat b)
 87 {
 88     int i,j,k;
 89     Mat ans;
 90     for(i=0;i<len;i++)
 91     {
 92         for(j=0;j<len;j++)
 93         {
 94             ans.a[i][j]=0;
 95             for(k=0;k<len;k++)
 96             {
 97                 if(a.a[i][k] && b.a[k][j])
 98                 {
 99                     ans.a[i][j]+=a.a[i][k]*b.a[k][j];
100                     if(ans.a[i][j]>=mod)
101                         ans.a[i][j]%=mod;
102                 }
103             }
104         }
105     }
106     return ans;
107 }
108 
109 Mat getE()
110 {
111     int i,j;Mat c;
112     for(i=0;i<61;i++)
113         for(j=0;j<61;j++)
114             c.a[i][j]=(i==j);
115     return c;
116 }
117 
118 Mat solve(Mat a,int k)
119 {
120     Mat res=e;
121     all=1;int b=26;
122     while(k)
123     {
124         if(k&1)
125         {
126             res=mulPow(res,a);
127             all*=b;
128             if(all>=mod)
129                 all%=mod;
130         }
131         a=mulPow(a,a);
132         b=b*b;
133         if(b>=mod)
134             b%=mod;
135         k=k>>1;
136     }
137     return res;
138 }
139 
140 int main()
141 {
142     int i,j,k,temp;e=getE();
143     //freopen("D:\\in.txt","r",stdin);
144     while(scanf("%d%d",&n,&m)==2)
145     {
146         num=1;
147         memset(root,0,sizeof(struct node));
148         for(i=0;i<n;i++)
149         {
150             scanf("%*c%s",str);
151             insert(str);
152         }
153         add_Fail();
154         Mat res;
155         int id=0,id1;
156         for(i=0;i<num;i++)
157         {
158             if(root[i].cnt==0)
159             {    
160                 id1=0;
161                 for(j=0;j<num;j++)
162                 {
163                     if(!root[j].cnt)
164                     {
165                         int cc=0;
166                         for(k=0;k<26;k++)
167                         {
168                             if(root[j].jump[k]==root+i)
169                                 cc++;
170                         }
171                         res.a[id][id1]=cc;
172                         id1++;
173                     }
174                 }
175                 id++;
176             }
177         }
178         len=id;
179         all=1;
180         res=solve(res,m);
181         temp=0;
182         for(i=0;i<len;i++)
183         {
184             temp=(temp+res.a[i][0]);
185             if(temp>=mod)
186                 temp%=mod;
187         }
188         all=all-temp;
189         if(all<0)
190             all+=mod;
191         printf("%d\n",all);
192     }
193     return 0;
194 }

 

posted @ 2012-09-12 15:45  Accept  阅读(585)  评论(0编辑  收藏  举报