POJ 1625

什么鬼,真的是有负数的吗?我在字符加上了128才过了。dp[i][j],经过i步到达j状态的路径数。转移很容易了,建个trie图就可以,由前一步可连通到和更新即可。

另外,要用到大数和AC自动机DP

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <climits>
  6 #include <string.h>
  7 #include <queue>
  8 #include <cmath>
  9 #include <map>
 10 #include <vector>
 11 #define LL  __int64
 12 using namespace std;
 13
 14 const __int64 forward=100000000000000000LL;
 15 const int root=0;
 16 const int Maxn=550;
 17 int idx[600];
 18 struct BigNumber{
 19     LL num[16];
 20     void initial(){
 21         for(int i=0;i<15;i++)
 22         num[i]=0;
 23     }
 24 };
 25 BigNumber add_BigNumber(BigNumber a,BigNumber b){
 26     BigNumber c;
 27     c.initial();
 28     for(int i=0;i<15;i++){
 29         c.num[i]=c.num[i]+a.num[i]+b.num[i];
 30         c.num[i+1]=c.num[i]/forward;
 31         c.num[i]%=forward;
 32     }
 33     return c;
 34 }
 35 BigNumber dp[510][55];
 36 struct Node{
 37     bool tag;
 38     int next[55];
 39     int fail;
 40     void initial(){
 41         tag=false;
 42         memset(next,-1,sizeof(next));
 43         fail=-1;
 44     }
 45 };
 46 int que[Maxn],head,tail,tot;
 47 Node trie[Maxn];
 48 int dictsize,step;
 49 char str[60];
 50
 51 void build_ac(){
 52     head=tail=0;
 53     que[tail++]=root;
 54     int tmp,p;
 55     while(head!=tail){
 56         tmp=que[head++];
 57         p=-1;
 58         for(int i=0;i<dictsize;i++){
 59             if(trie[tmp].next[i]!=-1){
 60                 if(tmp==root) trie[trie[tmp].next[i]].fail=root;
 61                 else{
 62                     p=trie[tmp].fail;
 63                     while(p!=-1){
 64                         if(trie[p].next[i]!=-1){
 65                             trie[trie[tmp].next[i]].fail=trie[p].next[i];
 66                             break;
 67                         }
 68                         p=trie[p].fail;
 69                     }
 70                     if(p==-1) trie[trie[tmp].next[i]].fail=root;
 71                 }
 72                 if(trie[trie[trie[tmp].next[i]].fail].tag)
 73                 trie[trie[tmp].next[i]].tag=true;
 74                 que[tail++]=trie[tmp].next[i];
 75             }
 76             else{    //trie[tmp].next[i]==-1
 77                 if(tmp==root) trie[tmp].next[i]=root;
 78                 else{
 79                     p=trie[tmp].fail;
 80                     while(p!=-1){
 81                         if(trie[p].next[i]!=-1){
 82                             trie[tmp].next[i]=trie[p].next[i];
 83                             break;
 84                         }
 85                         p=trie[p].fail;
 86                     }
 87                     if(p==-1)    trie[tmp].next[i]=root;
 88                 }
 89             }
 90         }
 91     }
 92 }
 93
 94 int main(){
 95     int n,m,p,pt;
 96     cin>>n>>m>>p;
 97         for(int i=0;i<Maxn;i++) trie[i].initial();
 98         head=tail=tot=0;
 99         dictsize=n; step=m;
100         cin>>str;
101         for(int i=0;i<n;i++)
102         idx[str[i]+128]=i;
103     //    cout<<idx[‘a‘]<<endl;
104     //    cout<<idx[‘b‘]<<endl;
105         for(int i=0;i<p;i++){
106             cin>>str;
107             pt=root;int k=0;
108             int len=strlen(str);
109             while(k<len){
110                 if(trie[pt].next[idx[str[k]+128]]==-1) trie[pt].next[idx[str[k]+128]]=++tot;
111                 pt=trie[pt].next[idx[str[k]+128]];
112                 k++;
113             }
114             trie[pt].tag=true;
115         }
116 //        cout<<"YES"<<endl;
117         build_ac();
118 //        cout<<"YEA"<<endl;
119         for(int i=0;i<=tot;i++){
120             for(int j=0;j<=step;j++)
121             dp[i][j].initial();
122         }
123         dp[0][0].num[0]=1;
124         for(int k=0;k<step;k++){
125             for(int i=0;i<=tot;i++){
126                 if(!trie[i].tag){
127                     for(int j=0;j<dictsize;j++){
128                         if(!trie[trie[i].next[j]].tag)
129                         dp[trie[i].next[j]][k+1]=add_BigNumber(dp[trie[i].next[j]][k+1],dp[i][k]);
130                     }
131                 }
132             }
133         }
134         BigNumber ans;
135         ans.initial();
136     //    cout<<tot<<endl;
137         for(int i=0;i<=tot;i++){
138             if(!trie[i].tag){
139                 ans=add_BigNumber(ans,dp[i][step]);
140             }
141         }
142         bool flag=false;
143         for(int i=14;i>=1;i--)
144             if(ans.num[i]>0||flag){
145                 if(flag)
146                 printf("%017I64d",ans.num[i]);
147                 else
148                 printf("%I64d",ans.num[i]);
149                 flag=true;
150             }
151         if(flag)
152         printf("%017I64d\n",ans.num[0]);
153         else{
154             printf("%I64d\n",ans.num[0]);
155         }
156     return 0;
157 }

时间: 2024-10-28 10:55:53

POJ 1625的相关文章

poj 1625 Censored!(AC自动机+DP+高精度)

题目链接:poj 1625 Censored! 题目大意:给定N,M,K,然后给定一个N字符的字符集和,现在要用这些字符组成一个长度为M的字符串,要求不包 括K个子字符串. 解题思路:AC自动机+DP+高精度.这题恶心的要死,给定的不能匹配字符串里面有负数的字符情况,也算是涨姿势 了,对应每个字符固定偏移128单位. #include <cstdio> #include <cstring> #include <queue> #include <vector>

poj 1625 Censored!

Censored! http://poj.org/problem?id=1625 Time Limit: 5000MS   Memory Limit: 10000K       Description The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish) consists of exactly M letters witho

POJ 1625 Censored!(AC自动机,DP)

http://poj.org/problem?id=1625 Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 8266   Accepted: 2229 Description The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish)

POJ 1625 Censored ( Trie图 &amp;&amp; DP &amp;&amp; 高精度 )

题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中的步骤是一样的,只不过最后的DP状态转移方式 2778 是利用了矩阵进行转移的,那是因为需要构造的串的长度非常长!只能利用矩阵转移.但是这道题需要构造的串的长度最多也就只有 50 ,可以利用普通的DP方法进行转移.我们定义 DP[i][j] 为以长度为 i 以字符 j 为结尾的串的种类数是多少,那么

POJ 1625 Censored! (AC自动机 + 高精度 + DP)

题目链接:Censored! 解析:AC自动机 + 高精度 + 简单DP. 字符有可能会超过128,用map映射一下即可. 中间的数太大,得上高精度. 用矩阵快速幂会超时,简单的DP就能解决时间的问题. AC代码: #include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include <queue> #include <map>

poj 1625 (AC自动机好模版,大数好模版)

题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后缀的字符串是否包含非法字符串(p个字符串中的任何一个). 状态转移方程:f(i, j)  += f(i-1, k) f(i, j)表示长度为i的字符串,结尾为字符j,方程j和k的关系可以从自动机中失配关系直接获得(j是k的后继结点). 总之感觉是好东西,快存下来 大数模版: #include <cs

POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)

题目链接:Censored! 解析:AC自己主动机 + 高精度 + 简单DP. 字符有可能会超过128.用map映射一下就可以. 中间的数太大.得上高精度. 用矩阵高速幂会超时,简单的DP就能解决时间的问题. AC代码: #include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include <queue> #include <map&

[AC自动机+dp+高精度] poj 1625 Censored!

题意: 给一个长度为N的字符串,表示有N个字符可用. 再给p个不能含有的病毒串. 为你长度为M的串不含有任意一个病毒串的方案数. 思路: 由于不需要取模,50^50需要用到高精度. 因为题目的字符串大于32所以可以直接scanf输入. 输入完map一下就好了. 就是裸的自动机dp了. 代码: #include"stdio.h" #include"algorithm" #include"string.h" #include"iostrea

[转] POJ字符串分类

POJ 1002 - 487-3279(基础)http://acm.pku.edu.cn/JudgeOnline/problem?id=1002题意:略解法:二叉查找数,map,快排... POJ 1200 - Crazy Search(基础)http://acm.pku.edu.cn/JudgeOnline/problem?id=1200题意:找出不相同的子串数量,字母表大小和子串长度会给定,这题很推荐hash入门者一做解法:hash(建议karp-rabin) POJ 1204 - Word