字符串专项:LA 4126
2013-07-04 23:28
344 查看
一道AC自动机+状压DP,将M个字符串建一个AC自动机,注意将字符串插入tire树时,注意可能会有多个字符公用一个尾结点,需要注意val值的更新。
状态方程不难得出dp[dep][u][st]=sum{dp[dep+1][ch[u][i]][st|val[ch[u][i]]]|0<i<sigma_size},至于字典序打印方案,只需dfs一遍即可。
状态方程不难得出dp[dep][u][st]=sum{dp[dep+1][ch[u][i]][st|val[ch[u][i]]]|0<i<sigma_size},至于字典序打印方案,只需dfs一遍即可。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; typedef long long LL; const int sigma=26; int n,m; char s[12][12]; int ch[110][sigma],val[110],sz; int f[110]; void init(){sz=1;val[0]=0;memset(ch[0],0,sizeof(ch[0]));memset(val,0,sizeof(val));} int idx(char c){return c-'a';} void insert(char* s,int v) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]|=v; } void getfail() { queue<int> q; f[0]=0; for(int c=0;c<sigma;c++) { int u=ch[0][c]; if(u) {f[u]=0;q.push(u);} } while(!q.empty()) { int r=q.front();q.pop(); for(int c=0;c<sigma;c++) { int u=ch[r][c]; if(!u) {ch[r][c]=ch[f[r]][c];continue;} q.push(u); int v=f[r]; while(v&&!ch[v][c]) v=f[v]; f[u]=ch[v][c]; val[u]|=val[f[u]]; } } } LL dp[110][30][1<<10]; int vis[110][30][1<<10]; char rec[25]; LL dfs(int u,int l,int st) { if(l==n) { if(st==((1<<m)-1)) return dp[u][l][st]=1; else return dp[u][l][st]=0; } if(vis[u][l][st]) return dp[u][l][st]; vis[u][l][st]=1; LL& ans=dp[u][l][st]; for(int i=0;i<sigma;i++) { ans+=dfs(ch[u][i],l+1,st|val[ch[u][i]]); } return ans; } void print(int u,int l,int st) { if(l==n) { rec[l]=0;printf("%s\n",rec);return; } for(int i=0;i<sigma;i++) if(dp[ch[u][i]][l+1][st|val[ch[u][i]]]) { rec[l]='a'+i; print(ch[u][i],l+1,st|val[ch[u][i]]); } } int main() { int kase=1; while(scanf("%d%d",&n,&m)!=EOF) { if(!n&&!m) break; init(); for(int i=1;i<=m;i++) { scanf("%s",s[i]); insert(s[i],(1<<(i-1))); } getfail(); memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); LL ans=dfs(0,0,0); printf("Case %d: %lld suspects\n",kase++,ans); if(ans<=42) { print(0,0,0); } } return 0; }
相关文章推荐
- 字符串专项:LA 2755
- 字符串专项:LA 3490
- 字符串专项:LA 5913
- ** 标准模板库 STL-2 编程题#4: 字符串操作(Coursera 程序设计与算法 专项课程3 C++程序设计 郭炜、刘家瑛;OpenJudge)
- 字符串hash LA 4513 Stammering Aliens
- 数学专项counting:LA 4064
- 刷题笔记:牛客字符串专项练习7
- 数学专项counting:LA 3357
- * 期末考试 编程题#7:字符串排序(Coursera 程序设计与算法 专项课程3 C++程序设计 郭炜、刘家瑛;函数对象作参数)
- 字符串专项:UVa 10298
- 刷题笔记:牛客字符串专项练习2
- 刷题笔记:牛客字符串专项练习4
- 专项练习:数组和字符串(三)
- 刷题笔记:牛客字符串专项练习3
- 刷题笔记:牛客字符串专项练习5
- 动态规划专项advanced:LA 4625
- LA 4513 hash表示字符串后缀
- LA 4394 刷字符串
- 杂题专项:LA 3602
- LA 4513 Stammering Aliens(字符串hash)