HDU3247-(AC自动机+spfa+状压dp)
来源:互联网 发布:中国向何处去 知乎 编辑:程序博客网 时间:2024/06/06 00:23
题意:给你n个资源串和m个病毒串然后让你求最少需要多少个01字符才能做出不含病毒串并且含有所有的资源串的字符串
题解:先跑一边AC自动机然后求出所有结点是资源串的结尾但是不是病毒串的结尾的结点,最后求这些结点到其他结点的最短距离,注意的是初始是空串所有0那个结点也要算进去,因为结点对应的数值很大但是满足条件的很少所以我们要给满足条件的结点重新编号,最后就是二维dp(第一维表示含有哪几个资源串,第二维表示毅哪个结点结尾)而其对应的数值就是到达该状态的时候的最小长度
#include<iostream>#include<cstring>#include<queue>#include<cstdio>#include<cstring>using namespace std;#define mes(a,b) memset(a,b,sizeof(a))const int maxnode = 1e5+5;const int inf = 0x3f3f3f3f;int n,m;struct tried{ int ch[maxnode][2]; int v[maxnode]; int vis[maxnode]; int f[maxnode]; int dis[maxnode]; int dp[1234][205]; int path[205][205]; int pos[205]; int sz,cnt; void init(){ sz = 1; mes(ch[0],0); } void insert(char *s,bool flag,int id){ int len = strlen(s); int u = 0; for(int i = 0; i < len; i++){ int d = s[i]-'0'; if(!ch[u][d]){ mes(ch[sz],0); v[sz] = 0; vis[sz] = 0; f[sz] = 0; ch[u][d] = sz++; } u = ch[u][d]; } flag?vis[u] = 1:v[u]|=(1<<id); } void getfail(){ int u = 0; queue<int>q; for(int i = 0; i < 2; i++) if(ch[u][i]) q.push(ch[u][i]); while(!q.empty()){ u = q.front(); q.pop(); vis[u] |= vis[f[u]]; v[u] |= v[f[u]]; for(int i = 0; i < 2; i++){ if(!ch[u][i]){ ch[u][i] = ch[f[u]][i]; continue; } int ret = ch[u][i]; f[ret] = ch[f[u]][i]; q.push(ret); } } } void spfa(int s){ queue<int>q; q.push(pos[s]); mes(dis,inf); dis[pos[s]] = 0; while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < 2; i++){ int ret = ch[u][i]; if(!vis[ret]){ if(dis[ret]==inf){ dis[ret] = dis[u]+1; q.push(ret); } } } } for(int i = 0; i < cnt; i++) path[s][i] = dis[pos[i]]; } int solve(){ cnt = 0; pos[cnt++] = 0; for(int i = 0; i < sz; i++) if(v[i]&&!vis[i]) pos[cnt++] = i; for(int i = 0; i < cnt; i++) spfa(i); mes(dp,inf); dp[0][0] = 0; int d = (1<<n); for(int i = 0; i < d; i++) for(int j = 0; j < cnt; j++){ if(dp[i][j]==inf) continue; for(int k = 0; k < cnt; k++){ int nex = v[pos[k]]|i; dp[nex][k] = min(dp[nex][k],dp[i][j]+path[j][k]); } } int ans = inf; for(int j = 0; j < cnt; j++) ans = min(ans,dp[d-1][j]); return ans; }}word;char s[1005];int main(){ while(scanf("%d%d",&n,&m),n||m){ word.init(); for(int i = 0; i < n; i++){ scanf("%s",s); word.insert(s,0,i); } for(int i = 0; i < m; i++){ scanf("%s",s); word.insert(s,1,i); } word.getfail(); printf("%d\n",word.solve()); } return 0;}
阅读全文
0 0
- HDU3247-(AC自动机+spfa+状压dp)
- HDU3247 Resource Archiver(AC自动机+DP)
- hdu3247 深刻理解ac自动机+bfs预处理最短路+状压DP
- AC自动机+状态压缩dp+BFS求最短路+hdu3247
- hdu3247 Resource Archiver AC自动机+状态压缩DP
- [AC自动机+spfa+状压dp] hdu 3247 Resource Archiver
- hdu2825-(AC自动机+状压DP)
- poj 3691 DNA repair 【ac自动机 + dp + spfa】
- bzoj1030(ac自动机+dp)
- hdu2296-(AC自动机+DP)
- HDU2296(AC自动机+DP)
- ac自动机(dp)<AC自动机模板> ---高精度处理
- hdu2825 Wireless Password(AC自动机+状压dp)
- hdu2825 Wireless Password(AC自动机+状压dp)
- zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)
- HDU4758 Walk Through Squares(AC自动机+状压DP)
- HDU 2825-Wireless Password(AC自动机+状压DP)
- HDU 4758-Walk Through Squares(AC自动机+状压DP)
- Shell脚本8种字符串截取方法总结
- [简单题]Human Readable Time(Python 实现)
- Linux常用命令
- 使用webpack犯过的一个错误
- jdk_API中文文档下载汇总
- HDU3247-(AC自动机+spfa+状压dp)
- k路合并_败者树算法
- C++常见面试题(三)-static总结
- 2426: [HAOI2010]工厂选址
- Python的基础语法(具体程序示例)
- leetcode---search-in-rotated-sorted-array---查找
- Solr Date类型的哪些你不得不了解的细节
- minGW下载与编译器安装
- erlang基础入门