poj 1625 dp+大数+ac自动机

题意:

在一个国家当中,给你一个词汇书,你可以用里面所有的字母拼凑出一个单词来,但是在这个国家当中存在一些禁用的单词,那么现在问你在不违反规则的情况下,你能尽可能的多拼凑出相应的单词来。

那么也就是说拼凑的单词当中不能够出现禁用的单词的字段。

后面看到网上教程当中的dp状态转移,傻眼了。。这都可以。

dp[i+1][cnt]=dp[i+1][cnt]+dp[i][j],我所理解的就是在i+1这个位置上面我放上cnt这个字符,将之前可行的数目累加到长度为i+1的基础上,其实我认为这个与其说是dp,倒不如说是一种递推。

而其中的ac自动机就是用来判断其中新拼凑的单词当中是否出现过类似的字串,出现了就不能够累加到相应的dp值上。

大数当然是因为方案的种类数多了之后难以用int整形存下。

代码:

View Code
  1 //大数+dp+ac自动机
  2 #include<iostream>
  3 #include<stdlib.h>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<queue>
  7 
  8 const int Type=55;
  9 const int Max=800;
 10 const int base=100000000;
 11 const int bit=30;
 12 
 13 using namespace std;
 14 
 15 struct node
 16 {
 17        node *next[Type];
 18        node *fail;
 19        int id,sum;
 20 }tree[Max];
 21 
 22 struct BigNum
 23 {
 24        int num[bit];
 25        int len;
 26        BigNum()
 27        {
 28            len=1;
 29            memset(num,0,sizeof(num));
 30        }
 31 }dp[Type][Max];
 32 
 33 int MM(int a,int b)
 34 {
 35     return a>b?a:b;
 36 }
 37 
 38 BigNum operator+(BigNum a,BigNum b)
 39 {
 40        BigNum c;
 41        c.len=MM(a.len,b.len);
 42        int k=0,t;
 43        for(int i=1;i<=c.len;i++)
 44        {
 45            t=a.num[i]+b.num[i]+k;
 46            k=t/base;
 47            c.num[i]=t%base;
 48        }
 49        while(k)
 50        {
 51            c.num[++c.len]=k%base;
 52            k/=base;
 53        }
 54        return c;
 55 }
 56 
 57 int n,m,p,tot;
 58 char s[Type],str[Type];
 59 int dx[5*Type];
 60 
 61 node *getroot()
 62 {
 63       tot=0;
 64       tot++;
 65       tree[tot].fail=NULL;
 66       memset(tree[tot].next,NULL,sizeof(tree[tot].next));
 67       tree[tot].id=tot;
 68       tree[tot].sum=0;
 69       return &tree[tot];
 70 }
 71 node *root;
 72 
 73 node *getnode()
 74 {
 75       tot++;
 76       tree[tot].fail=root;
 77       memset(tree[tot].next,NULL,sizeof(tree[tot].next));
 78       tree[tot].id=tot;
 79       tree[tot].sum=0;
 80       return &tree[tot];
 81 }
 82 
 83 void insert()
 84 {
 85      node *tmp=root;
 86      int i=0;
 87      while(str[i])
 88      {
 89            int index=dx[str[i]+128];
 90            if(tmp->next[index]==NULL)tmp->next[index]=getnode();
 91            tmp=tmp->next[index];
 92            i++;
 93      }
 94      tmp->sum++;
 95 }
 96 
 97 void build_ac()
 98 {
 99      queue<node*> q;
100      while(!q.empty())q.pop();
101      q.push(root);
102      while(!q.empty())
103      {
104            node *tmp=q.front();
105            q.pop();
106            node *ff;
107            for(int i=0;i<n;i++)
108                if(tmp->next[i]!=NULL)
109                {
110                   q.push(tmp->next[i]);
111                   for(ff=tmp->fail;ff!=NULL;ff=ff->fail)
112                   {
113                       if(ff->next[i]!=NULL)
114                       {
115                           tmp->next[i]->fail=ff->next[i];
116                           if(ff->next[i]->sum==1)tmp->next[i]->sum=1;
117                           break;
118                       }
119                   }
120                }
121      }
122 }
123 
124 void solution()
125 {
126      dp[0][1].num[1]=1;
127      for(int i=0;i<m;i++)
128      {
129          for(int j=1;j<=tot;j++)
130          {
131              node *tmp=&tree[j];
132              for(int k=0;k<n;k++)
133              {
134                  if(tmp->next[k]!=NULL)
135                  {
136                     int index=tmp->next[k]->id;
137                     if(tmp->next[k]->sum==0)dp[i+1][index]=dp[i+1][index]+dp[i][j];
138                  }
139                  else
140                  {
141                      node *now=tmp->fail;
142                      for(;now!=NULL;now=now->fail)
143                      {
144                          if(now->next[k]!=NULL)
145                          {
146                              now=now->next[k];
147                              break;
148                          }
149                      }
150                      if(now==NULL)now=root;
151                      int index=now->id;
152                      if(now->sum==0)dp[i+1][index]=dp[i+1][index]+dp[i][j];
153                  }
154              }
155          }
156      }
157 }
158 void init()
159 {
160      memset(dx,-1,sizeof(dx));
161      tot=0;
162      gets(s);
163      for(int i=0;i<n;i++)
164      {
165          if(dx[s[i]+128]==-1)
166          dx[s[i]+128]=i;
167      }
168      root=getroot();
169      while(p--)
170      {
171          scanf("%s",str);
172          insert();
173      }
174 }
175 void Print()
176 {
177      BigNum answer;
178      for(int i=1;i<=tot;i++)
179          answer=answer+dp[m][i];
180      int ll=answer.len;
181      printf("%d",answer.num[ll]);
182      for(int j=ll-1;j>=1;j--)
183      {
184          if(answer.num[j]<base/10)printf("0");
185          if(answer.num[j]<base/100)printf("0");
186          if(answer.num[j]<base/1000)printf("0");
187          if(answer.num[j]<base/10000)printf("0");
188          if(answer.num[j]<base/100000)printf("0");
189          if(answer.num[j]<base/1000000)printf("0");
190          if(answer.num[j]<base/10000000)printf("0");
191          printf("%d",answer.num[j]);
192      }
193      printf("\n");
194 }
195 int main()
196 {
197     scanf("%d %d %d\n",&n,&m,&p);
198     init();
199     build_ac();
200     solution();
201     Print();
202     return 0;
203 }
posted @ 2013-03-07 20:33  诺小J  阅读(200)  评论(0编辑  收藏  举报