poj 1625 Censored! (ac自动机+dp)
来源:互联网 发布:怎样学习单片机编程 编辑:程序博客网 时间:2024/04/30 02:54
题意:
一个神奇的国度他们字母类型有n个,并且每句话必须是m个字母组成的,但是国王很奇葩,他设定了一些单词,只要句子中出现这样的单词那么造句的人就好入狱。给出了p个不能出现的单词。问有多少种句子可以出现。
题解:
ac自动上的dp,第一次做参照了bin神的代码,很神奇啊,ac自动机上也可以dp 0 0!
好了我以自己理解来分析这题。
首先,我们要将所给的n个字符进行处理,因为这n个字符有可能不是以阿斯科马值相邻的,那么我们用map离散化。
接着,我们将限制的串插入自动机中,凡是出现end[i]==0的就是可行的串。
然后,建ac自动机时,要注意一点,如果适配指针对应的节点是限制串(fail[i]==1)那么对应的这个指向适配指正的对应节点也应该是限制串,这个要好好理解下。
最后我们只要这样设置状态dp[step][i]走了step步,并且以i节点为结尾的合法句子个数。只要枚举上一步的节点是哪个即可。注意要排出限制的:if(end[i]==1)continue;
最后一点,答案太大,要用大数存。我懒得写,可耻的盗用了别人的大数类。
#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<map>#include<set>using namespace std;#define B(x) (1<<(x))typedef long long ll;const int oo=0x3f3f3f3f;const ll OO=1LL<<61;const ll MOD=10007;const int maxn=1005;const int SIZE=110;char buff[maxn];map<char,int>mat;struct AC{ int next[SIZE][256],fail[SIZE],end[SIZE],Q[SIZE*256]; int root,cnt; void Init() { cnt=0; root=newNode(); } int newNode() { for(int i=0;i<256;i++) next[cnt][i]=-1; end[cnt++]=0; return cnt-1; } void Insert(char buff[]) { int now=root; int len=strlen(buff); for(int i=0,k;i<len;i++) { k=mat[buff[i]]; if(next[now][k]==-1) next[now][k]=newNode(); now=next[now][k]; } end[now]=1;///这个单词是否存在 } void build() { fail[root]=root; int front,rear; front=rear=0; int now=root; for(int i=0;i<256;i++) { if(next[now][i]==-1) next[now][i]=root; else { fail[next[now][i]]=root; Q[rear++]=next[now][i]; } } while(front<rear) { now=Q[front++]; if(end[fail[now]]) end[now]=1;///这句话非常重要,没加wa一发 for(int i=0;i<256;i++) { if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q[rear++]=next[now][i]; } } } }/* void Search(char buff[]) { int now=root; int len=strlen(buff); for(int i=0;i<len;i++) { now=next[now][buff[i]]; int temp=now; while(temp!=root) { if(end[temp]) StrId.insert(end[temp]); ans[end[temp]]++; temp=fail[temp]; } } }*/ void Debug() { for(int i=0;i<cnt;i++) { printf("id=%3d fail=%3d end=%3d child=[",i,fail[i],end[i]); for(int j=0;j<26;j++) printf(" %3d",next[i][j]); printf(" ]\n"); } }};AC ac;///大数struct BigInt{ const static int mod = 10000; const static int DLEN = 4; int a[600],len; BigInt() { memset(a,0,sizeof(a)); len = 1; } BigInt(int v) { memset(a,0,sizeof(a)); len = 0; do { a[len++] = v%mod; v /= mod; }while(v); } BigInt(const char s[]) { memset(a,0,sizeof(a)); int L = strlen(s); len = L/DLEN; if(L%DLEN)len++; int index = 0; for(int i = L-1;i >= 0;i -= DLEN) { int t = 0; int k = i - DLEN + 1; if(k < 0)k = 0; for(int j = k;j <= i;j++) t = t*10 + s[j] - '0'; a[index++] = t; } } BigInt operator +(const BigInt &b)const { BigInt res; res.len = max(len,b.len); for(int i = 0;i <= res.len;i++) res.a[i] = 0; for(int i = 0;i < res.len;i++) { res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0); res.a[i+1] += res.a[i]/mod; res.a[i] %= mod; } if(res.a[res.len] > 0)res.len++; return res; } BigInt operator *(const BigInt &b)const { BigInt res; for(int i = 0; i < len;i++) { int up = 0; for(int j = 0;j < b.len;j++) { int temp = a[i]*b.a[j] + res.a[i+j] + up; res.a[i+j] = temp%mod; up = temp/mod; } if(up != 0) res.a[i + b.len] = up; } res.len = len + b.len; while(res.a[res.len - 1] == 0 &&res.len > 1)res.len--; return res; } void output() { printf("%d",a[len-1]); for(int i = len-2;i >=0 ;i--) printf("%04d",a[i]); printf("\n"); }};BigInt dp[2][SIZE];int main(){ int n,m,p; while(scanf("%d %d %d",&n,&m,&p)!=EOF) { scanf("%s",buff); mat.clear(); for(int i=0;buff[i];i++) mat[buff[i]]=i; ac.Init(); for(int i=1;i<=p;i++) { scanf("%s",buff); ac.Insert(buff); } ac.build(); int now=0,pre=1; dp[now][0]=1; for(int i=1;i<ac.cnt;i++) dp[now][i]=0; for(int t=1;t<=m;t++) { now^=1; pre^=1; for(int i=0;i<ac.cnt;i++) dp[now][i]=0; for(int i=0;i<ac.cnt;i++) { if(ac.end[i])continue;///存在这样的路径跳过. for(int j=0;j<n;j++) { int k=ac.next[i][j]; if(ac.end[k])continue; dp[now][k]=dp[now][k]+dp[pre][i]; } } } BigInt ans=0; for(int i=0;i<ac.cnt;i++) ans=ans+dp[now][i]; ans.output(); } return 0;}/**5 5 5abcdebeeedcbadeebbaedans=1024*/
0 0
- poj 1625 Censored!//AC自动机+DP+大数
- POJ--1625[Censored!] AC自动机+DP+高精度
- POJ 1625 Censored【AC自动机+DP+大数】
- POJ 1625 Censored!(AC自动机+DP)
- 【AC自动机+DP+大数】 POJ 1625 Censored!
- poj 1625 Censored!(AC自动机+DP+高精度)
- POJ 1625 Censored!(AC自动机,DP)
- poj 1625 Censored! (ac自动机+dp)
- poj 1625 Censored! AC自动机+dp+高精度
- [AC自动机+dp+高精度] poj 1625 Censored!
- POJ 1625 Censored(AC自动机+dp)
- POJ 1625 Censored! AC自动机+DP+高精度 *
- POJ 1625 Censored!(AC自动机+DP)
- poj 1625 Censored! 【AC自动机 + DP + 强力大数模版】
- poj 1625 Censored! AC自动机+DP +高精度 + C艹 + java
- POJ 1625 Censored! AC自动机 简单DP 高精度
- POJ 1625 Censored! (AC自动机+DP+高精度,5级)
- poj 1625 Censored!(AC自动机+DP+高精)
- 项目里程碑评审的关注点
- UVALive 4244 Party Party Party(HDU 2779 && Sicily 1663)
- HDOJ 1875 畅通工程再续(prim)
- Python:重启
- Linux运维工程师初级到高级学习线路图
- poj 1625 Censored! (ac自动机+dp)
- Python 中的编码转换 编码方案 中文解码 gbk , utf ,unicode
- read-python-code-with-cscope-on-emacs
- 使用压缩池对读取自标准的谁的数据进行压缩,然后将其写到标准输出
- Scala 自学笔记 集合
- java中获取文件夹大小
- NullPointerException丢失异常堆栈信息
- 浅谈JSON
- C++之函数