poj 1625 AC自动机上的DP
来源:互联网 发布:百人牛牛作弊辅助软件 编辑:程序博客网 时间:2024/05/01 08:38
好题!搞了N久终于AC!
【题意】
给定N个字符集合和P个禁用的字符串,求长度为M的合法字符串个数。
【题解】
显然是AC自动机上的DP。
令dp[i][j]表示长度为i,状态为j的字符串个数。
按自动机的图转移即可,但要注意细节。
贡献几组数据。
50 50 10
qwertyuiop[]\asdfghjkl;'zxcvbnm,./ QWERTYUIOP{}|AS
aegaegu
etoijqt
tquqi
witowwt
zxcjnc
oeit
potieq
iojge
nvoq
piqper
ans=8881647922834867244791415981705771412427494861672253136057167374729235842468240763290
1 1 1
a
a
ans=0
5 10 3
abcde
abc
bc
c
ans=1048576
#include <iostream>#include <queue>using namespace std;const int maxn=800,maxm=55,base=100000000,kind=55;struct node{ int sum,id; node* ch[kind]; node* fail;}a[maxn];struct num{ int g[20]; int len; num() { memset(g,0,sizeof(g)); len=1; }}dp[maxm][maxn];char s[maxm];int dx[400];int n,m,p,tot=0;node* getroot(){ tot++; int i; for (i=0;i<kind;i++) a[tot].ch[i]=0; a[tot].fail=0; a[tot].id=tot; a[tot].sum=0; return &a[tot];}node* root=getroot();node* getnode(){ tot++; int i; for (i=0;i<kind;i++) a[tot].ch[i]=0; a[tot].fail=root; a[tot].id=tot; a[tot].sum=0; return &a[tot];}void ins(char* s){ int i,k,len=strlen(s); node* now=root; for (i=0;i<len;i++) { k=dx[s[i]+128]; if (now->ch[k]==0) now->ch[k]=getnode(); now=now->ch[k]; } now->sum++;} void init(){ int i; char st[maxm]; scanf("%d%d%d\n",&n,&m,&p); gets(s); for (i=0;i<n;i++) dx[s[i]+128]=i; for (i=1;i<=p;i++) { scanf("%s",st); ins(st); }}queue<node*> q;void build(){ int i,k; node* now,*ff; q.push(root); while (!q.empty()) { now=q.front(); q.pop(); for (i=0;i<kind;i++) if (now->ch[i]!=0) { q.push(now->ch[i]); for (ff=now->fail;ff!=0;ff=ff->fail) if (ff->ch[i]!=0) { now->ch[i]->fail=ff->ch[i]; if (ff->ch[i]->sum==1) now->ch[i]->sum=1; break; } } }}num operator +(num a,num b){ num c=num(); int i,t,k=0,len=max(a.len,b.len); for (i=1;i<=len;i++) { t=a.g[i]+b.g[i]+k; k=t/base; c.g[i]=t%base; } while (k) { c.g[++len]=k%base; k/=base; } c.len=len; return c;}void DP(){ int i,j,k; dp[0][1].g[1]=1; for (i=0;i<m;i++) for (j=1;j<=tot;j++) { node* now=&a[j]; for (k=0;k<n;k++) if (now->ch[k]!=0) { int ct=now->ch[k]->id; if (now->ch[k]->sum==0) dp[i+1][ct]=dp[i+1][ct]+dp[i][j]; } else { node* tmp=now->fail; for (;tmp!=0;tmp=tmp->fail) if (tmp->ch[k]!=0) { tmp=tmp->ch[k]; break; } if (tmp==0) tmp=root; int ct=tmp->id; if (tmp->sum==0) dp[i+1][ct]=dp[i+1][ct]+dp[i][j]; } }}void print(){ int i,j; num ans=num(); for (i=1;i<=tot;i++) ans=ans+dp[m][i]; j=ans.len; printf("%d",ans.g[j]); for (i=j-1;i>=1;i--) { if (ans.g[i]<base/10) printf("0"); if (ans.g[i]<base/100) printf("0"); if (ans.g[i]<base/1000) printf("0"); if (ans.g[i]<base/10000) printf("0"); if (ans.g[i]<base/100000) printf("0"); if (ans.g[i]<base/1000000) printf("0"); if (ans.g[i]<base/10000000) printf("0"); printf("%d",ans.g[i]); } printf("\n");}int main(){ freopen("pin.txt","r",stdin); freopen("pou.txt","w",stdout); init(); build(); DP(); print(); return 0;}
- poj 1625 AC自动机上的DP
- Poj 2778 /1625 / 3691 AC自动机上的DP
- poj--1625Censored!+AC自动机上的dp+大数
- POJ 1625 AC自动机+DP
- 第一次看AC自动机上的dp
- poj 1625 Censored!//AC自动机+DP+大数
- POJ--1625[Censored!] AC自动机+DP+高精度
- POJ 1625(ac自动机+dp+高精度)
- POJ 1625 Censored【AC自动机+DP+大数】
- poj 1625 (AC自动机 + dp + 高精度(java) )
- POJ 1625 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!
- 黑马程序员——函数部分总结
- Iterator Categories
- vi/vim使用
- 关于Win7系统hiberfil.sys及pagefile.sys两个隐藏文件
- Encounter ORA-03113 Error when create spfile from pfile
- poj 1625 AC自动机上的DP
- C++笔记(2)小问题
- 白天求生存,晚上谋发展
- C++的重要性质:虚函数和多态性
- C# 如何用socket进行通信
- 百度音乐接口
- 局部线性嵌入(LLE)算法解释
- 查询某个用户的表信息
- spring环境搭建