[POJ2243]考研路茫茫——单词情结
2016-03-29 22:07
239 查看
又是AC自动机上用矩乘优化DP= =
其实和上一题基本一样。。。补集转化思想。。
只是要多弄一个小矩阵求(26^1+26^2+....+26^L),并且也要求f的总和(因为是长度<=L)
直接调上一题的伪板子了= =
喜闻乐见CE了好几发。。。就因为iostream里有next这个名字的函数>_<(那我上一题怎么没CE啊摔
View Code
其实和上一题基本一样。。。补集转化思想。。
只是要多弄一个小矩阵求(26^1+26^2+....+26^L),并且也要求f的总和(因为是长度<=L)
直接调上一题的伪板子了= =
喜闻乐见CE了好几发。。。就因为iostream里有next这个名字的函数>_<(那我上一题怎么没CE啊摔
#include<cstdio> #include<cstring> #define ll long long #define ull unsigned long long using namespace std; int dl[33],fail[33],num[33]; int ch[33][26],tot,next[33][26]; ull mp[36][36]; ull c[36][36],tmp[36][36],ans; int i,j,k,n,m,l,r,cnt; bool gg[103]; char s[23]; ll tm[103],t[103]; inline void trie(int n){ int i,p=0; for(i=0;i<n;i++){ s[i]-='a'; if(!ch[p][s[i]])ch[p][s[i]]=++tot,p=tot; else p=ch[p][s[i]]; } gg[p]=1;//printf("gg: %d\n",p); } inline void getfail(){ int l=0,r=1,i,j,now,p;dl[1]=0; while(l<r){ now=dl[++l];//printf(" %d fail:%d gg:%d\n",now,fail[now],gg[now]); for(i=0;i<26;i++)if(ch[now][i]){ j=ch[now][i];//printf(" %d-->%d\n",now,j); for(p=fail[now];p&&!ch[p][i];p=fail[p]); if(!now)fail[j]=0;else fail[j]=ch[p][i]; dl[++r]=j;gg[j]|=gg[fail[j]]; } } } inline void getnext(){ l=0,r=1;int i,now,p;dl[1]=0; while(l<r){ now=dl[++l];//printf(" %d\n",now); for(i=0;i<26;i++){ if(ch[now][i]){ if(gg[ch[now][i]])next[now][i]=-1; else next[now][i]=ch[now][i],dl[++r]=ch[now][i]; } else{ for(p=fail[now];p&&!ch[p][i];p=fail[p]); next[now][i]=gg[ch[p][i]]?-1:ch[p][i]; } // printf("%d %d next:%d\n",now,i,next[now][i]); } } } inline void upd(){ cnt=0;int i,j; for(i=1;i<=r;i++) num[dl[i]]=++cnt; for(i=1;i<=r;i++){ j=dl[i]; for(k=0;k<26;k++)if(next[j][k]!=-1) mp[num[next[j][k]]][num[j]]++; } // for(i=1;i<=r;puts(""),i++) // for(j=1;j<=r;j++)printf(" %lld",mp[i][j]); } inline void multoc(){ register int i,j,k; for(i=1;i<=cnt;i++) for(j=1;j<=cnt;j++) for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*c[k][j]; for(i=1;i<=cnt;i++)memcpy(c[i],tmp[i],(cnt+1)<<3); } inline void multomp(){ register int i,j,k; for(i=1;i<=cnt;i++) for(j=1;j<=cnt;j++) for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*mp[k][j]; for(i=1;i<=cnt;i++)memcpy(mp[i],tmp[i],(cnt+1)<<3); } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ for(i=1;i<=n;i++)scanf("%s",s),trie(strlen(s)); getfail(),getnext(),upd(); cnt++; for(i=1;i<=cnt;i++)mp[cnt][i]=1; cnt++,mp[cnt][cnt]=26,cnt++,mp[cnt][cnt-1]=mp[cnt][cnt]=1; // for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf(" %llu",mp[i][j]); for(i=1;i<=cnt;i++)c[i][i]=1; /* tm[1]=1; for(i=1;i<=m;i++){ for(j=1;j<=cnt;j++) for(k=1,t[j]=0;k<=cnt;k++)t[j]=(t[j]+mp[j][k]*tm[k])%modd; memcpy(tm,t,sizeof(t)); }*/ while(m){ if(m&1) multoc(); m>>=1;if(m)multomp(); // for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf(" %llu",c[i][j]); } // for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf(" %llu",c[i][j]); //for(i=1,ans=0;i<=cnt;i++)ans=(ans+c[i][1])%modd; ull ans=c[cnt][cnt-1]*26; for(i=1;i<=cnt-2;i++)ans-=c[i][1]; printf("%I64u\n",ans+1); memset(mp,0,sizeof(mp)),memset(c,0,sizeof(c)), memset(ch,0,(tot+1)*4*26),memset(next,0,(tot+1)*4*26),memset(fail,0,(tot+1)<<2),memset(gg,0,tot+1),tot=0; } // for(i=1,ans=0;i<=cnt;i++)ans=(ans+tm[i])%modd; // printf("%lld\n",ans); return 0; }
View Code
相关文章推荐
- java SE基础(Collection接口概述)
- java毕向东听课笔记6(单例设计模式)
- PHP(第一天)
- return阻止js继续向下执行
- 结对项目—词频统计2
- Android各种Manager
- 计算机重复启动问题原因及修复
- Android笔记:实现圆角的Button
- poj2282 poj3286 数位递归
- 单元测试
- Iphone 英语语言下通讯录排序问题
- ExtJs4.2—Window组件
- ABP源码分析十六:DTO的设计
- 使用cJSON解析JSON字符串
- 忘记mysql密码解决方法
- 视角
- request.getParameterMap()
- 校园网络
- PHP的基本知识点
- 音视频同步原理