标签:rom using mission roo other 建立 eof 并且 一个
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7175 Accepted Submission(s): 2361
#include <stdio.h> #include <algorithm> #include <iostream> #include <string.h> #include <queue> using namespace std; int num[1<<10+10]; int dp[30][110][1<<10]; const int MOD=20090717; int n,m,s; struct Trie { int Next[110][26];//26是这里讨论26个小写字母的情况,根据情况修改 int fail[110],end[110];//end数组表示以该节点结尾的字符串的数量 int root,L;//L用来标记节点序号,以广度优先展开的字典树的序号 int newnode() //建立新节点 { for(int i = 0;i < 26;i++) Next[L][i] = -1; //将该节点的后继节点域初始化 end[L++] = 0; return L-1; //返回当前节点编号 } void init() //初始化操作 { L = 0; root = newnode(); } void insert(char buf[],int id) { int len = strlen(buf); int now = root; for(int i = 0;i < len;i++) { if(Next[now][buf[i]-‘a‘] == -1) //如果未建立当前的后继节点,建立新的节点 Next[now][buf[i]-‘a‘] = newnode(); now = Next[now][buf[i]-‘a‘]; } end[now]|=(1<<id);//以该节点结尾的单词的特征值 } void build() { queue<int>Q; //用广度优先的方式,将树层层展开 fail[root] = root; for(int i = 0;i < 26;i++) if(Next[root][i] == -1) Next[root][i] = root; else { fail[Next[root][i]] = root; Q.push(Next[root][i]); } while( !Q.empty() ) { int now = Q.front(); Q.pop(); end[now]|=end[fail[now]]; for(int i = 0;i < 26;i++) if(Next[now][i] == -1) Next[now][i] = Next[fail[now]][i];//该段的最后一个节点匹配后,跳到拥有最大公共后缀的fail节点继续匹配 else { fail[Next[now][i]]=Next[fail[now]][i];//当前节点的fail节点等于它前驱节点的fail节点的后继节点 Q.push(Next[now][i]); } } } int solve() { int ans=0; for(int i=0;i<=n;i++) for(int j=0;j<L;j++) for(int k=0;k<(1<<m);k++) dp[i][j][k]=0; dp[0][0][0]=1; for(int i=0;i<n;i++) for(int j=0;j<L;j++) for(int k=0;k<(1<<m);k++) { if(dp[i][j][k]>0) { for(int r=0;r<26;r++) { int newi=i+1; int newj=Next[j][r]; int newk=(k|end[newj]); dp[newi][newj][newk]+=dp[i][j][k]; dp[newi][newj][newk]%=MOD; // cout<<newi<<" "<<newj<<" "<<newk<<" "<<dp[newi][newj][newk]<<endl; } } } for(int k=0;k<(1<<m);k++) { if(num[k]<s)continue; for(int j=0;j<L;j++) { ans+=dp[n][j][k]; ans%=MOD; } } return ans; } }; char buf[110]; Trie ac; int main() { for(int i=0;i<(1<<10);i++) { num[i]=0; for(int j=0;j<10;j++) if(i&(1<<j)) num[i]++; } while(scanf("%d%d%d",&n,&m,&s)!=EOF){ if(n==0&&m==0&&s==0)break; ac.init(); for(int i=0;i<m;i++) { scanf("%s",buf); ac.insert(buf,i); } ac.build(); cout<<ac.solve()<<endl; } return 0; }
HDU 2825 Wireless Password(AC自动机)
标签:rom using mission roo other 建立 eof 并且 一个
原文地址:http://www.cnblogs.com/a249189046/p/7633615.html