码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2825 (Aho-Corasick & 状压DP) - xgtao -

时间:2016-07-24 22:18:51      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

 

给出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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!