给出m(m<=10)个模板串,问长度为n(n<=25)的字符串包含至少k个模板串的种类数,对20090717取模。
套路,有多个模板串考虑Aho-Corasick,因为想了很久找不到什么可行办法做,就考虑Dp,因为m<=10,所以可以有状压来检查当前状态下已经包含多少个模板串了,因为在一棵trie树上,那么定义状态也好定义,dp[len][id][s]表示长度为len时处在第id个节点并且状态为s,转移方程为dp[len+1][nextid][s|nexts] += dp[len][id][s],因为内存够用我就没有用滚动数组了,最后再把s中大于等于k个的状态的长度为n的所有节点的dp值加起来。
#include <cstdio> #include <iostream> #include <queue> #include <cstring> #include <algorithm> #define LL long long using namespace std; //Globel define const int N = 30; const int alp = 26; const int mod = 20090717; int n,m,k; int ncnt; int dp[N][110][1035]; struct node{ int id,set; node *ch[alp],*fail; void init(){ set = 0; for(int i = 0;i < alp;++i)ch[i] = NULL; } }trie[110]; //end Globel define node *newnode(){ node *p = &trie[ncnt]; p->init(); p->id = ncnt++; return p; } void insert(node *root,char *s,int i){ node *p = root; int set = 0; while(*s != ‘\0‘){ if(!p->ch[*s-‘a‘])p->ch[*s-‘a‘] = newnode(); p = p->ch[*s-‘a‘]; ++s; } p->set |= (1<<i); } void _buildfail(node *root){ queue <node *> q; root->fail = NULL; q.push(root); while(!q.empty()){ node *p = q.front();q.pop(); for(int i = 0;i < alp;++i){ if(p->ch[i]){ node *next = p->fail; while(next && !next->ch[i])next = next->fail; p->ch[i]->fail = next ? next->ch[i] : root; p->ch[i]->set |= p->ch[i]->fail->set; q.push(p->ch[i]); } else p->ch[i] = (p==root) ? root:p->fail->ch[i]; } } } int count(int set){ int cnt = 0; for(int i = 0;i < 10;++i){ if(set&(1<<i))cnt++; } return cnt; } int main(){ while(scanf("%d%d%d",&n,&m,&k) && n+m+k){ ncnt = 0; memset(trie,0,sizeof(trie)); node *root = newnode(); for(int i = 0;i < m;++i){ char buf[N]; scanf("%s",buf); insert(root,buf,i); } _buildfail(root); memset(dp,0,sizeof(dp)); dp[0][0][0] = 1; for(int a = 0;a < n;++a) for(int b = 0;b < ncnt;++b) for(int s = 0;s < (1<<m);++s){ if(!dp[a][b][s])continue; for(int c = 0;c < alp;++c){ node *nxt = trie[b].ch[c]; if(!nxt)continue; int &ret = dp[a+1][nxt->id][s|nxt->set]; ret = (ret+dp[a][b][s])%mod; } } int ans = 0; for(int s = 0;s < (1<<m);++s){ if(count(s)>=k){ for(int i = 0;i < ncnt;++i)ans = (ans+dp[n][i][s])%mod; } } cout<<ans<<endl; } return 0; }
时间: 2024-11-23 14:43:03