题目地址:http://poj.org/problem?id=1625
题目意思:
给你一个字典,里面有n个不同的字符
然后给你p个不允许出现的字符串
要你求出在由字典里的字符组成的一个m长度的字符串不含禁止字符串的种数有多少
解题思路:
假设在一个AC自动机上,状态j的长度已经有i了,用dp[i][j]表示
那么dp[i+1][tmp] += dp[i][j] 其中tmp这个节点可以由j合法的转移(合法就是不会出现禁止的情况)
再就是本题的数据规模很大,50^50,所以要用大数
再就是要注意几个细节
比如最后大数的结果为0的话
或者是当上面说的j已经是非法点了,那么就不能跳转了
再就是本题输入的char可能会有到255,那么会出现负数,所以我用了hash的方法来重定向下标
下面上代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxnode = 120; const int size=256; int hash[size]; int wordn,m,p; struct AC { int ch[maxnode][size]; int f[maxnode]; bool val[maxnode]; int sz; void init() { sz=1; memset(ch[0],-1,sizeof(ch[0])); val[0]=false; } void insert(char *s) { int len = strlen(s); int u=0; for(int i=0;i<len;i++) { int c=hash[s[i]+128]; if(-1 == ch[u][c]) { memset(ch[sz],sizeof(ch[sz])); val[sz]=false; ch[u][c] = sz++; } u=ch[u][c]; } val[u] = true; } void getfail() { queue<int> q; for(int i=0;i<wordn;i++) { int u = ch[0][i]; if(-1!=u) { f[u]=0; q.push(u); } else ch[0][i]=0; } while(!q.empty()) { int r=q.front(); q.pop(); //printf("q\n"); val[r] |= val[f[r]]; for(int i=0;i<wordn;i++) { int &v=ch[r][i]; if(-1!=v) { q.push(v); f[v]=ch[f[r]][i]; } else { v=ch[f[r]][i]; } } } } }ac; struct bignumber { int a[100]; void init() { memset(a,sizeof(a)); } void print() { int j=99; while(a[j]==0) j--; if(j<0) { printf("0\n"); return ; } while(j>=0) { printf("%d",a[j]); j--; } printf("\n"); } }; void add(bignumber &x,bignumber y) { for(int i=0;i<99;i++) { x.a[i]+=y.a[i]; x.a[i+1]+=x.a[i]/10; x.a[i]=x.a[i]%10; } } bignumber dp[55][120]; void dp_ac() { memset(dp,sizeof(dp)); dp[0][0].a[0]=1; for(int i=0;i<m;i++) { for(int j=0;j<ac.sz;j++) { if(ac.val[j]) continue; for(int k=0;k<wordn;k++) { int tmp = ac.ch[j][k]; if(!ac.val[tmp] && !ac.val[j]) { add(dp[i+1][tmp],dp[i][j]); } } } } bignumber ans; ans.init(); for(int i=0;i<ac.sz;i++) { add(ans,dp[m][i]); } ans.print(); } int main() { while(~scanf("%d%d%d",&wordn,&m,&p)) { ac.init(); char str[100]; getchar(); gets(str); memset(hash,sizeof(hash)); for(int i=0;i<wordn;i++) { hash[str[i]+128]=i; } for(int i=0;i<p;i++) { gets(str); ac.insert(str); } ac.getfail(); dp_ac(); } return 0; }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。