HDU - 3247 Resource Archiver (AC自动机,状压dp)

\(\quad\)Great! Your new software is almost finished! The only thing left to do is archiving all your n resource files into a big one.
\(\quad\)Wait a minute… you realized that it isn’t as easy as you thought. Think about the virus killers. They’ll find your software suspicious, if your software contains one of the m predefined virus codes. You absolutely don’t want this to happen.
\(\quad\)Technically, resource files and virus codes are merely 01 strings. You’ve already convinced yourself that none of the resource strings contain a virus code, but if you make the archive arbitrarily, virus codes can still be found somewhere.
\(\quad\)Here comes your task (formally): design a 01 string that contains all your resources (their occurrences can overlap), but none of the virus codes. To make your software smaller in size, the string should be as short as possible.

Input

\(\quad\)There will be at most 10 test cases, each begins with two integers in a single line: n and m (2 <= n <= 10, 1 <= m <= 1000). The next n lines contain the resources, one in each line. The next m lines contain the virus codes, one in each line. The resources and virus codes are all non-empty 01 strings without spaces inside. Each resource is at most 1000 characters long. The total length of all virus codes is at most 50000. The input ends with n = m = 0.

Output

\(\quad\)For each test case, print the length of shortest string.

Sample Input

2 2
1110
0111
101
1001
0 0

Sample Output

5

题意

\(\quad\)就是给你\(n\)个需要的串和\(m\)个病毒串,最后让你构造一个字符串,包含所有需要的串,不包括任何病毒串。

思路

\(\quad\)先讲\(n+m\)个串全部插入ac自动机中,然后去构造\(fail\)指针的时候注意将\(fail\)节点的信息传递给子节点。
\(\quad\)首先容易想到\(dp[i][j]\)表示ac自动机上状态为\(i\),包含需要串的状态为\(j\)时所需要的最少字符串数。但是数据范围\(i<=(略大于)5e4,j<=1024\),会\(MLE\)
\(\quad\)观察数据范围可以发现\(n<<m\),那么说明,在ac自动机上,无用的节点占大多数,那么就可以找出全部有用的节点,用\(bfs\)求出所有有用节点两两之间的最小距离,然后直接在这些有用的点上跑\(dp\)就可以了,那么可以得到新的\(dp\)方程。
\(\quad\)\(dp[i][j]\)表示到有用节点\(i\),包含需要串的状态为\(j\)时所需要的最少字符长度。
\(\quad\)\(cnt[i]\)表示有用节点\(i\)上包含需要串的状态。
\(\quad\)\(cc[i][j]\)表示从有用节点\(i\)走到有用节点\(j\)需要的最少字符数。
\(\quad\)\(dp[k][j|cnt[k]] = min(dp[k][cnt[k]],dp[i][j]+cc[i][k])\)
\(\quad\)最后在遍历一遍\(dp[i][mx]\),就可以得到答案。

/***************************************************************> File Name    : a.cpp> Author       : Jiaaaaaaaqi> Created Time : 2019年04月29日 星期一 11时10分00秒***************************************************************/#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 6e4 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;int n, m;
int cas, tol, T;char s[1010];
struct AC {int node[maxn][2], fail[maxn], cnt[maxn], vir[maxn];int root, sz;int newnode() {mes(node[++sz], 0);cnt[sz] = vir[sz] = 0;return sz;}void init() {sz = 0;root = newnode();}void insert(char *s, int f, int id) {int len = strlen(s+1);int rt = root;for(int i=1; i<=len; i++) {int k = s[i]-'0';if(node[rt][k] == 0) {node[rt][k] = newnode();}rt = node[rt][k];}if(f == 1)  cnt[rt] |= (1<<(id-1));else    vir[rt] = 1;}void build() {queue<int> q;while(!q.empty())   q.pop();fail[root] = root;for(int i=0; i<=1; i++) {if(node[root][i] == 0) {node[root][i] = root;} else {fail[node[root][i]] = root;q.push(node[root][i]);}}while(!q.empty()) {int u = q.front();q.pop();vir[u] |= vir[fail[u]];cnt[u] |= cnt[fail[u]];for(int i=0; i<=1; i++) {if(node[u][i] == 0) {node[u][i] = node[fail[u]][i];} else {fail[node[u][i]] = node[fail[u]][i];q.push(node[u][i]);}}}}int dis[maxn], point[500];bool vis[maxn];int cc[500][500], dp[500][1030];void bfs(int st) {queue<int> q;while(!q.empty())   q.pop();for(int i=1; i<=sz; i++)    dis[i] = inf;mes(vis, 0);q.push(point[st]);dis[point[st]] = 0;vis[point[st]] = 1;while(!q.empty()) {int u = q.front();q.pop();for(int i=0; i<=1; i++) {int k = node[u][i];if(vir[k])  continue;if(vis[k])  continue;dis[k] = dis[u]+1;vis[k] = true;q.push(k);}}for(int i=1; i<=tol; i++) {cc[st][i] = dis[point[i]];}}void handle() {tol = 0;point[++tol] = 1;for(int i=1; i<=sz; i++) {if(cnt[i]) {point[++tol] = i;}}for(int i=1; i<=tol; i++) {bfs(i);}//     for(int i=1; i<=tol; i++) {//         for(int j=1; j<=tol; j++) {//             printf("%d%c", cc[i][j], j==tol ? '\n' : ' ');//         }//     }//     for(int i=1; i<=tol; i++) {//         printf("cnt[%d] = %d\n", i, cnt[point[i]]);//     }}int solve() {int mx = (1<<n)-1;for(int i=1; i<=tol; i++) {for(int j=0; j<=mx; j++) {dp[i][j] = inf;}}dp[1][0] = 0;for(int j=0; j<=mx; j++) {for(int i=1; i<=tol; i++) {if(dp[i][j] == inf) continue;// printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);for(int k=1; k<=tol; k++) {if(i == k)  continue;dp[k][j|cnt[point[k]]] = min(dp[k][j|cnt[point[k]]], dp[i][j]+cc[i][k]);}}}int ans = inf;for(int i=1; i<=tol; i++) {ans = min(ans, dp[i][mx]);}return ans;}
} ac;int main() {while(scanf("%d%d", &n, &m), n||m) {ac.init();for(int i=1; i<=n; i++) {scanf("%s", s+1);ac.insert(s, 1, i);}for(int i=1; i<=m; i++) {scanf("%s", s+1);ac.insert(s, 2, i);}ac.build();ac.handle();int ans = ac.solve();printf("%d\n", ans);}return 0;
}

转载于:https://www.cnblogs.com/Jiaaaaaaaqi/p/10789881.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

space index.php 7-14,disk_free_space()

disk_free_space()(PHP 4 > 4.1.0, PHP 5, PHP 7)返回目录中的可用空间说明disk_free_space(string$directory):float给出一个包含有一个目录的字符串&#xff0c;本函数将根据相应的文件系统或磁盘分区返回可用的字节数。参数$directory文件系统目录或者磁盘分区。Note:如果…

云专网和云专线的区别_企业更适合互联网专线还是云专线联网?

随着云计算、移动应用及全球化的发展&#xff0c;纵横企业专网20年的MPLS专线弊端逐渐暴露&#xff0c;MPLS专线越来越难以满足企业的业务发展需求&#xff0c;而云计算、SaaS及移动应用具有天然的互联网属性。为什么“互联网”可以取代专线?互联网的持续发展&#xff0c;为取…

composer安装thinkphp

https://getcomposer.org/Composer-Setup.exe 正常安装composer以后,执行composer create-project topthink/thinkphp myapp安装thinkphp.转载于:https://www.cnblogs.com/lijurui/p/6362012.html

wordpress 插件_如何为您的Web应用程序创建WordPress插件

wordpress 插件by Feedier by Alkalab由Feedier通过Alkalab 如何为您的Web应用程序创建WordPress插件 (How to create a WordPress plugin for your web app) Today, we are going to see how to create a very simple WordPress plugin for any web app that needs to insert…

Android 软键盘相关问题

1. windowSoftInputMode属性的使用 Android使用windowSoftInputMode来控制Activity 的主窗口与包含屏幕软键盘的窗口的交互方式。 该属性的设置影响两个方面&#xff1a; 当 Activity 成为用户注意的焦点时软键盘的状态 — 隐藏还是可见。对 Activity 主窗口所做的调整 — 是否…

git php框架,如何用Git安装TP框架

本篇文章主要给大家介绍如何用Git安装Thinkphp框架。关于TP框架的安装&#xff0c;想必大家都知道较为常见的方式是通过composer安装tp框架。首先简单的给大家介绍下Git和TP框架。Git是一个开源的分布式版本控制系统&#xff0c;可以快速&#xff0c;高效地处理从小型到大型项目…

C#EF中,使用类似于SQL中的% 模糊查询

最近在做项目的时候需要使用到模糊查询,但是后台使用EF写的 而不是ADO或者是Dapper,如果是这样的话,我们就可以使用Sql语句直接进行模糊查询 现在我们需要在LINQ中使用类似于模糊查询 在EF中有两个方法:StartsWith()和EndWith() StartsWith(): 在转到定义时 我们可以看见,这个方…

android toast居中显示_Android Toast 设置到屏幕中间,自定义Toast的实现方法,及其说明...

Android Toast用于在手机屏幕上向用户显示一条信息&#xff0c;一段时间后信息会自动消失。信息可以是简单的文本&#xff0c;也可以是复杂的图片及其他内容(显示一个view)。1.简单用法Toast.makeText(midlet.getApplicationContext(), "用户名不能为空", Toast.LENG…

leetcode103. 二叉树的锯齿形层次遍历(bfs)

给定一个二叉树&#xff0c;返回其节点值的锯齿形层次遍历。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。例如&#xff1a; 给定二叉树 [3,9,20,null,null,15,7],3/ \9 20/ \15 7 返回…

LintCode Find the Weak Connected Component in the Directed Graph

原题链接在这里&#xff1a;http://www.lintcode.com/en/problem/find-the-weak-connected-component-in-the-directed-graph/ 题目&#xff1a; Find the number Weak Connected Component in the directed graph. Each node in the graph contains a label and a list of its…

简单了解tengine

Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上&#xff0c;针对大访问量网站的需求&#xff0c;添加了很多高级功能和特性。最终目标是打造一个高效、稳定、安全、易用的Web平台。1、基本的HTTP服务器特性1.处理静态文件&#xff0c;索引文件以及自动索引&#xff…

服务器创建多个dhcp服务_如何在15分钟内创建无服务器服务

服务器创建多个dhcp服务by Charlee Li通过李李 如何在15分钟内创建无服务器服务 (How to create a serverless service in 15 minutes) The word “serverless” has been popular for quite a while. When Amazon released the AWS Lambda service in 2015, many tools emerg…

php snoopy视频教程,php的Snoopy类

用了两天这个类&#xff0c;发现很好用。获取请求网页里面的所有链接&#xff0c;直接使用fetchlinks就可以&#xff0c;获取所有文本信息使用fetchtext(其内部还是使用正则表达式在进行处理)&#xff0c;还有其它较多的功能&#xff0c;如模拟提交表单等。使用方法&#xff1a…

网页解析 css

网页解析 css转载于:https://www.cnblogs.com/guozepingboke/p/10792298.html

如何看pg数据库版本号_查看pg数据库版本

PostgreSQL 基本命令链接&#xff1a;http://blog.itpub.net/28602568/viewspace-1841163/标题&#xff1a;PostgreSQL 基本命令作者&#xff1a;&#xff4c;ōττ&#xff52;&#xff59;©版权所有[文章允许转载,但必须以链接方式注明源地址,否则追究法律责任.]安装步…

leetcode1091. 二进制矩阵中的最短路径(bfs)

在一个 N N 的方形网格中&#xff0c;每个单元格有两种状态&#xff1a;空&#xff08;0&#xff09;或者阻塞&#xff08;1&#xff09;。一条从左上角到右下角、长度为 k 的畅通路径&#xff0c;由满足下述条件的单元格 C_1, C_2, ..., C_k 组成&#xff1a;相邻单元格 C_i …

lock和synchronized的同步区别与选择

区别如下&#xff1a; 1. lock是一个接口&#xff0c;而synchronized是java的一个关键字&#xff0c;synchronized是内置的语言实现&#xff1b;&#xff08;具体实现上的区别在《Java虚拟机》中有讲解底层的CAS不同&#xff0c;以前有读过现在又遗忘了。&#xff09; 2. syn…

首页显示登陆用户名php,首页登录后怎么在首页显示用户名以及隐藏登录框?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼index.php&#xff1a;登录页面用户名&#xff1a;密码&#xff1a;没有账号&#xff1f;立即注册——————————————————————————doaction.php&#xff1a;header("Content-type:text/html;charsetutf…

react中使用构建缓存_通过在React中构建Tic Tac Toe来学习ReasonML

react中使用构建缓存3. 7. 2018: UPDATED to ReasonReact v0.4.23. 7. 2018&#xff1a;更新为ReasonReact v0.4.2 You may have heard of Reason before. It’s a syntax on top of OCaml that compiles to both readable JavaScript code and to native and bytecode as well…

echart vue 图表大小_vue里echarts自适应窗口大小改变

echarts的图表提供了一个resize方法可以自适应屏幕窗口改变&#xff0c;而重新渲染图表大小的功能。因此我们只要监听浏览器的窗口改变的resize事件&#xff0c;再结合echarts的图表&#xff0c;就可以实现我们想要的功能了。如果是单个图表的情况的话用window.onresize myCha…