zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    栈和队列
    数组的遍历查找
    字符串的子串
    两个字符串
    字符串的遍历
    字符串的替换
    数组和矩阵
    Django 自带的ORM增删改查
    what's the CRSF ??
    Rabbitmq -Publish_Subscribe模式- python编码实现
  • 原文地址:https://www.cnblogs.com/ka200812/p/2681900.html
Copyright © 2011-2022 走看看