[jzoj3472]【NOIP2013模拟联考8】匹配(match)
2017-12-08 21:25
447 查看
Description
给定k个字符串以及长度为n的母串可选字母的集合,问母串要完整出现给定的k个字符串的方案数,答案模1000000007,字符仅包含小写字母。
Solution
注意到 k 很小 可以状压很容易想到利用 AC 自动机 来记录当前匹配到各个字符串的位置
枚举下一个出现的字符即可
注意 在更新时,指针走到了一个节点j,不能只加上这一个节点的贡献,而要把其对应的fail都给更新到
或者 你可以提前把这些点一并考虑
Code
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define fo(i,x,y) for (int i=(x);i<=(y);++i) #define fd(i,x,y) for (int i=(x);i>=(y);--i) #define oo 2139062143 using namespace std; typedef long long ll; typedef double db; const int N=110,M=11,K=9,Mo=1e9+7,LEN=33; const int P=K*LEN; int n,k; char st[K][LEN]; int d[P]; int all; int f [P][256+100]; bool bcz[26]; int chos[26]; struct ACAutoMachine{ int chd[P][26]; int fail[P]; int sz,pt,bz[P]; void insert(char *c,int w) { int len=strlen(c),tmp=0; fo(i,0,len-1) { int now=c[i]-'a'; if(!chd[tmp][now]) { chd[tmp][now]=++sz; memset(chd[sz],0,sizeof chd[sz]); } tmp=chd[tmp][now]; } bz[tmp]|=(1<<(w-1)); } bool pd[P]; void Getfail() { memset(pd,0,sizeof pd); int hd=0,tl=0; pd[0]=1; fo(i,0,25) if(chd[0][i]) d[++tl]=chd[0][i],pd[d[tl]]=1; while(hd++<tl) { int now=d[hd]; fo(i,0,25) if(chd[now][i]) { int v=chd[now][i]; if(pd[v]) continue; pd[v]=1; d[++tl]=v; int rt=fail[now]; while(!chd[rt][i]&&rt) rt=fail[rt]; fail[v]=chd[rt][i]; } } fo(i,0,sz) { bz[i]|=bz[fail[i]]; fo(j,0,25) { int p=i; while(p&&!chd[p][j]) p=fail[p]; if(chd[p][j]) next[i][j]=chd[p][j]; else next[i][j]=0; } } } int dt[2][P][2]; int tot[2]; int next[P][25]; void solve() { memset(f,0,sizeof f); f[0][0][0]=1; fo(i,0,n-1) { fo(j,0,sz) { fo(s,0,all) if(f[i][j][s]) { fo(cc,1,chos[0]) { int c=chos[cc]; int jj=next[j][c],ss=s|bz[jj]; f[i+1][jj][ss]=(f[i+1][jj][ss]+f[i][j][s])%Mo; } } } } int ans=0; fo(i,0,sz) { ans=(ans+f [i][all])%Mo; } printf("%d\n",ans); } void clear() { memset(bz,0,sizeof bz); memset(next,0,sizeof next); memset(fail,0,sizeof fail); memset(chd[0],0,sizeof chd[0]); pt=sz=0; } }ac; int m; int main() { scanf("%d%d\n",&n,&k); fo(i,1,k) { scanf("%s\n",st[i]); ac.insert(st[i],i); } ac.Getfail(); scanf("%d\n",&m); fo(i,1,m) { char tp=getchar(); while(!(tp<='z'&&tp>='a')) tp=getchar(); bcz[tp-'a']=1; } fo(i,0,25) if(bcz[i])chos[++chos[0]]=i; all=(1<<k)-1; ac.solve(); return 0; }
相关文章推荐
- [jzoj]3472. 【NOIP2013模拟联考8】匹配(match)(AC自动机+DP)
- 3472. 【NOIP2013模拟联考8】匹配(match)
- [jzoj]3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll)(匈牙利-二分图最大匹配)
- JZOJsenior3455.【NOIP2013模拟联考3】库特的向量(code)
- JZOJsenior3470.【NOIP2013模拟联考8】最短路(path)
- jzoj. 3450. 【NOIP2013模拟联考3】山峰(summits)
- JZOJ3455. 【NOIP2013模拟联考3】库特的向量(code)
- [jzoj]3468. 【NOIP2013模拟联考7】OSU!(osu) (期望DP)
- [jzoj]3486. 【NOIP2013模拟联考10】道路改建(rebuild)(缩环+Tarjan+拓扑+bitset记录状态)
- [jzoj]3498. 【NOIP2013模拟联考14】图形变换(transform) (计算几何+矩阵乘法)
- JZOJ 3468. 【NOIP2013模拟联考7】OSU!(osu)
- JZOJ 3447【NOIP2013模拟联考2】摘取作物
- jzoj3501 【NOIP2013模拟联考15】消息传递(news) 树形dp
- jzoj 3467. 【NOIP2013模拟联考7】最长上升子序列(lis) dfs+lis+手工栈
- jzoj3450【NOIP2013模拟联考3】山峰(summits,dfs)
- [jzoj]3479. 【NOIP2013模拟联考9】工作安排(work)
- JZOJsenior3488.【NOIP2013模拟联考11】矩形(rect)
- [jzoj]3480. 【NOIP2013模拟联考9】阿Q的停车场(park)(线段树+堆)
- JZOJ 3498【NOIP2013模拟联考14】图形变换
- [jzoj]3499. 【NOIP2013模拟联考15】人类基因组(genes) (单调队列、前缀和、线段树解一题)