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 }

 

你可能感兴趣的:(poj)