zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    HttpClient发送get,post接口请求
    java对象,引用的区别
    java基础知识面试题(41-95)
    java基础知识面试题(1-40)
    mysql增删改查sql语句
    java static成员变量方法和非static成员变量方法的区别
    zip和tgz以及exe的区别
    Java模拟网站登录02【转载】
    Java模拟登录系统抓取内容【转载】
    Java模拟登陆02【转载】
  • 原文地址:https://www.cnblogs.com/nuoyan2010/p/2948765.html
Copyright © 2011-2022 走看看