标签:
给出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;
}
hdu 2825 (Aho-Corasick & 状压DP) - xgtao -
标签:
原文地址:http://www.cnblogs.com/xgtao984/p/5701680.html