首页 > poj1625Censored!(AC自动机+dp)

poj1625Censored!(AC自动机+dp)

链接

第一次做这种题目,参考了下题解,相当于把树扯直了做DP,估计这一类题都是这个套路吧。

状态方程dp[i][next] = dp[i][next]+dp[i][j] ;dp[i][j]表示长度为i的第J个结点的时候满足题意的num,next为当前j点所能走到的下一个合法的结点。

需要用高精度,看到一些规范的高精度写法,觉得不错,有空整理下来。

不知道是不是我理解错了,按理说字符串病毒长度不应超过10.。但开到55依旧RE,开550AC。。。

  1 #include 
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 #include<set>
 10 using namespace std;
 11 #define N 110
 12 #define LL long long
 13 #define INF 0xfffffff
 14 const double eps = 1e-8;
 15 const double pi = acos(-1.0);
 16 const double inf = ~0u>>2;
 17 const int child_num = 110;
 18 const int BASE = 10000;
 19 const int DIG = 4;
 20 char s[N*100],vir[550];
 21 int id[2024];
 22 struct bignum
 23 {
 24      int a[110],len;
 25      bignum()
 26      {
 27          memset(a,0,sizeof(a));
 28          len = 1;
 29      }
 30      bignum(int v)
 31      {
 32          memset(a,0,sizeof(a));
 33          len = 0;
 34          do
 35          {
 36              a[len++] = v%BASE;
 37              v/=BASE;
 38          }while(v);
 39      }
 40      /*bignum(const char s[])
 41      {
 42          memset(a,0,sizeof(a));
 43          int k = strlen(s);
 44          len = k/DIG;
 45          if(k%DIG) len++;
 46          int cnt = 0;
 47          for(int i = k-1;  i >= 0 ; i-=DIG)
 48          {
 49              int t = 0;
 50              int kk = i-DIG+1;
 51              if(kk<0) kk =0;
 52              for(int j = kk ; j <= i ; j++)
 53              t = t*10+s[j]-'0';
 54              a[cnt++] = t;
 55          }
 56      }*/
 57      bignum operator + (const bignum &b)const
 58      {
 59          bignum res;
 60          res.len = max(len,b.len);
 61          int i;
 62          for(i = 0 ; i < res.len ;i ++)
 63          res.a[i] = 0;
 64          for(i = 0 ; i < res.len ; i++)
 65          {
 66              res.a[i] += ((i0)+((i0);
 67              res.a[i+1] += res.a[i]/BASE;
 68              res.a[i] = res.a[i]%BASE;
 69          }
 70          if(res.a[res.len]>0) res.len++;
 71          return res;
 72      }
 73      void output()
 74      {
 75          printf("%d",a[len-1]);
 76          for(int i = len-2 ; i >=0 ; i--)
 77          printf("%04d",a[i]);
 78          printf("
");
 79      }
 80 }dp[110][110];
 81 class AC
 82 {
 83     private:
 84     int ch[N][child_num];
 85     int Q[N];
 86     int val[N];
 87     int fail[N];
 88     //int id[N];
 89     int sz;
 90     public :
 91     void init()
 92     {
 93         fail[0] = 0;
 94         //for(int i = 0 ;i < child_num-32 ; i++)
 95         //id[i+32] = i;
 96     }
 97     void reset()
 98     {
 99         memset(val,0,sizeof(val));
100         memset(fail,0,sizeof(fail));
101         memset(ch[0],0,sizeof(ch[0]));
102         sz = 1;
103     }
104     void insert(char *a,int key)
105     {
106         int k = strlen(a),p = 0;
107         for(int i = 0 ; i < k ;i++)
108         {
109             int d = id[a[i]];
110             if(ch[p][d]==0)
111             {
112                 memset(ch[sz],0,sizeof(ch[sz]));
113                 ch[p][d] = sz++;
114             }
115             p = ch[p][d];
116         }
117         val[p] = key;
118     }
119     void construct(int n)
120     {
121         int i,head=0,tail = 0;
122         for(i = 0; i < n ; i++)
123         {
124             if(ch[0][i])
125             {
126                 Q[tail++] = ch[0][i];
127                 fail[ch[0][i]] = 0;
128             }
129         }
130         while(head!=tail)
131         {
132             int u = Q[head++];
133             val[u]|=val[fail[u]];
134             for(i = 0 ; i < n ; i++)
135             {
136                 if(ch[u][i])
137                 {
138                     Q[tail++] = ch[u][i];
139                     fail[ch[u][i]] = ch[fail[u]][i];
140                 }
141                 else ch[u][i] = ch[fail[u]][i];
142             }
143         }
144     }
145     void work(int m,int n)
146     {
147         int i,j,g;
148         for(i = 1; i <= m ;i++)
149             for(j = 0 ;j <= sz; j++)
150             dp[i][j] = bignum(0);
151         dp[0][0] = bignum(1);
152         for(i = 0 ; i < m ;i++)
153         {
154             for(j = 0 ; j < sz ;j++)
155             for(g = 0 ; g < n ; g++)
156             if(!val[ch[j][g]])
157             {
158                 dp[i+1][ch[j][g]]=dp[i+1][ch[j][g]]+dp[i][j];
159             }
160         }
161         bignum ans = bignum(0);
162         for(j = 0 ;j < sz ; j++)
163         ans=ans+dp[m][j];
164         ans.output();
165     }
166 }ac;
167 int main()
168 {
169     int n,m,i,p;
170     ac.init();
171     while(cin>>n>>m>>p)
172     {
173         cin>>s;
174         for(i = 0 ; i < n; i++)
175         id[s[i]] = i;
176         ac.reset();
177         for(i = 1;i <= p; i++)
178         {
179             scanf("%s",vir);
180             ac.insert(vir,1);
181         }
182         ac.construct(n);
183         ac.work(m,n);
184     }
185     return 0;
186 }
View Code

 

转载于:https://www.cnblogs.com/shangyu/p/3730815.html

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • $dp$。 这道题最关键的是这句话: 跳出思维局限大胆设状态,设$f_{x, i, j}$表示从$x$到根要经过$i$条公路,$j$条铁路的代价,那么对于一个叶子结点,有$f_{x, i, j} = c_x * (a_x + i) * (b_x + j)$,对于内部结点,有转移:   $f_{x, i, j} = min(f_{lso...

  • 合作者:201631062327,201631062128码云地址:https://gitee.com/LIUJIA6/WordCount3 一:项目说明 本次项目是在上次作业WorldCount的基础上,利用结对编程的思想,完成对WorldCount项目的功能扩展 -s 递归处理目录下符合条件的文件。(实现)-a 返回更复杂的数据(...

  • Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。 例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生...

  •   【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5972   【题目大意】   给出一个字符串,找出其中所有的符合特定模式的子串位置,符合特定模式是指,该子串的长度为n,并且第i个字符需要在给定的字符集合Si中    【题解】   利用ShiftAnd匹配算法。   bt[i]表示...

  • 首先我们可以发现如果错过了一个加油站,而继续往前走的时候没有油了,可以再假装之前经过加油站的时候加过油 于是我们维护一个大根堆,表示错过的加油站是哪些,每当没有油的时候从堆顶取出最大值加上去即可   1 /**************************************************************...

  • 用python编写乘法口诀表的方法 发布时间:2020-08-25 11:46:35 来源:亿速云 阅读:60 作者:小新 用python编写乘法口诀表的方法?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧! 第一种:使用for遍历循环嵌套for x in...

  • //很长一段时间我都只使用以下方式做数组循环,具体原因看数据 var aa = for (var i = 0, l = aa.length; i < l; i++) { var a = aa[i];} 数据采集图片来源于网友 很明显,for循环第二种方式完胜!!! 至于for in、forEach什么的,不知道甩他们多少...

  • 目录 1. Scene Graph Generation with External Knowledge and Image Reconstruction 2. Knowledge Acquisition for Visual Question Answering via Iterative Querying Author...

  • 基础题1: 输入一个正整数 n (1≤n≤10)和n 阶方阵a的元素,如果方阵a中的所有元素都沿主对角线对称,输出“Yes”, 否则,输出“No”。主对角线为从矩阵的左上角至右下角的连线,方阵a中的所有元素都沿主对角线对称指对所有i, k,a[i][k]和a[k][i]相等。输入输出示例如下: 输入: 3 1 2 3 4 5 6 7...

  • 程序流程控制 分支 顺序 循环 if switch&case 1 2 3 调整 break 1.6 前 switch(byte、short、char、int) 1.7 可放String 循环 while(次数不确定) do while for(确定次数) break(跳出本层循环) continue(跳出本次循环)     *   2...