Codeforces 717G Underfail(最小费用最大流 + AC自动机)
题目
Source
http://codeforces.com/problemset/problem/717/G
Description
You have recently fallen through a hole and, after several hours of unconsciousness, have realized you are in an underground city. On one of your regular, daily walks through the unknown, you have encountered two unusually looking skeletons called Sanz and P’pairus, who decided to accompany you and give you some puzzles for seemingly unknown reasons.
One day, Sanz has created a crossword for you. Not any kind of crossword, but a 1D crossword! You are given m words and a string of length n. You are also given an array p, which designates how much each word is worth — the i-th word is worth pi points. Whenever you find one of the m words in the string, you are given the corresponding number of points. Each position in the crossword can be used at most x times. A certain word can be counted at different places, but you cannot count the same appearance of a word multiple times. If a word is a substring of another word, you can count them both (presuming you haven’t used the positions more than x times).
In order to solve the puzzle, you need to tell Sanz what’s the maximum achievable number of points in the crossword. There is no need to cover all postions, just get the maximal score! Crossword and words contain only lowercase English letters.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 500) — the length of the crossword. The second line contains the crossword string. The third line contains a single integer m (1 ≤ m ≤ 100) — the number of given words, and next m lines contain description of words: each line will have a string representing a non-empty word (its length doesn't exceed the length of the crossword) and integer pi (0 ≤ pi ≤ 100). Last line of the input will contain x (1 ≤ x ≤ 100) — maximum number of times a position in crossword can be used.
Output
Output single integer — maximum number of points you can get.
Sample Input
6
abacba
2
aba 6
ba 3
3
Sample Output
12
分析
题目大概说给一个主串和几个有价值的模式串,某个模式串与主串匹配就能累加对应的价值,一个模式串可以在多个位置和主串匹配但同一个位置只能一次,此外主串各个字符最多可以用x次,问如何匹配使获得的价值最大。
各个模式串在主串匹配的位置可以用AC自动机找到,而这些位置相当于区间。
其实这题就相当于在一条数轴上选择最大权和的区间,使得各个点被覆盖的区间数不超过x。区间k覆盖问题,POJ3680。。
我都不会建图了。。要注意的是区间要处理成左闭右开形式,不然比如[1,1]这个区间建图就会出现负环了。
代码
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #include<algorithm>
- using namespace std;
- #define INF (1<<30)
- #define MAXN 555
- #define MAXM 555*1111
- struct Edge{
- int u,v,cap,cost,next;
- }edge[MAXM];
- int head[MAXN];
- int NV,NE,vs,vt;
- void addEdge(int u,int v,int cap,int cost){
- edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
- edge[NE].next=head[u]; head[u]=NE++;
- edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
- edge[NE].next=head[v]; head[v]=NE++;
- }
- bool vis[MAXN];
- int d[MAXN],pre[MAXN];
- bool SPFA(){
- for(int i=0;i<NV;++i){
- vis[i]=0;
- d[i]=INF;
- }
- vis[vs]=1;
- d[vs]=0;
- queue<int> que;
- que.push(vs);
- while(!que.empty()){
- int u=que.front(); que.pop();
- for(int i=head[u]; i!=-1; i=edge[i].next){
- int v=edge[i].v;
- if(edge[i].cap && d[v]>d[u]+edge[i].cost){
- d[v]=d[u]+edge[i].cost;
- pre[v]=i;
- if(!vis[v]){
- vis[v]=1;
- que.push(v);
- }
- }
- }
- vis[u]=0;
- }
- return d[vt]!=INF;
- }
- int MCMF(){
- int res=0;
- while(SPFA()){
- int flow=INF,cost=0;
- for(int u=vt; u!=vs; u=edge[pre[u]].u){
- flow=min(flow,edge[pre[u]].cap);
- }
- for(int u=vt; u!=vs; u=edge[pre[u]].u){
- edge[pre[u]].cap-=flow;
- edge[pre[u]^1].cap+=flow;
- cost+=flow*edge[pre[u]].cost;
- }
- res+=cost;
- }
- return res;
- }
- int tn,ch[55500][26],fail[55500];
- vector<int> vec[55500];
- void insert(char *s,int k){
- int x=0;
- for(int i=0; s[i]; ++i){
- int y=s[i]-'a';
- if(ch[x][y]==0) ch[x][y]=++tn;
- x=ch[x][y];
- }
- vec[x].push_back(k);
- }
- void getfail(){
- queue<int> que;
- for(int i=0; i<26; ++i){
- if(ch[0][i]) que.push(ch[0][i]);
- }
- while(!que.empty()){
- int x=que.front(); que.pop();
- for(int i=0; i<26; ++i){
- if(ch[x][i]){
- fail[ch[x][i]]=ch[fail[x]][i];
- que.push(ch[x][i]);
- }else ch[x][i]=ch[fail[x]][i];
- }
- }
- }
- int val[111],len[111];
- void ac(char *s){
- int x=0;
- for(int i=0; s[i]; ++i){
- int y=s[i]-'a';
- x=ch[x][y];
- for(int tmp=x; tmp; tmp=fail[tmp]){
- for(int j=0; j<vec[tmp].size(); ++j){
- int k=vec[tmp][j];
- addEdge(i-len[k]+1,i+1,1,-val[k]);
- }
- }
- }
- }
- char S[555],T[555];
- int main(){
- int n,m,x;
- scanf("%d%s%d",&n,S,&m);
- for(int i=1; i<=m; ++i){
- scanf("%s%d",T,val+i);
- len[i]=strlen(T);
- insert(T,i);
- }
- scanf("%d",&x);
- vs=n+1; vt=vs+1; NV=vt+1; NE=0;
- memset(head,-1,sizeof(head));
- addEdge(vs,0,x,0);
- addEdge(n,vt,x,0);
- for(int i=1; i<=n; ++i){
- addEdge(i-1,i,INF,0);
- }
- getfail();
- ac(S);
- printf("%d",-MCMF());
- return 0;
- }
Codeforces 717G Underfail(最小费用最大流 + AC自动机)的更多相关文章
- HDU1853 Cyclic Tour(最小费用最大流)
题目大概说给一张有向图,每条边都有权值,要选若干条边使其形成若干个环且图上各个点都属于且只属于其中一个环,问选的边的最少权值和是多少. 各点出度=入度=1的图是若干个环,考虑用最小费用最大流: 每个点 ...
- 最小费用最大流 POJ2195-Going Home
网络流相关知识参考: http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html 出处:優YoU http://blog.csdn. ...
- 网络流(最小费用最大流):POJ 2135 Farm Tour
Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: ...
- poj_2195Going Home(最小费用最大流)
poj_2195Going Home(最小费用最大流) 标签: 最小费用最大流 题目链接 题意: 有n*m的矩阵,H表示这个点是一个房子,m表示这个点是一个人,现在每一个人需要走入一个房间,已经知道的 ...
- Luogu--3381 【模板】最小费用最大流
题目链接 3381 [模板]最小费用最大流 手写堆版本 dijkstra 400+ms 看来优先队列的常数好大 #include<bits/stdc++.h> using namesp ...
- Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)
Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...
- Libre 6011 「网络流 24 题」运输问题 (网络流,最小费用最大流)
Libre 6011 「网络流 24 题」运输问题 (网络流,最小费用最大流) Description W 公司有m个仓库和n个零售商店.第i个仓库有\(a_i\)个单位的货物:第j个零售商店需要\( ...
- HDU5988/nowcoder 207G - Coding Contest - [最小费用最大流]
题目链接:https://www.nowcoder.com/acm/contest/207/G 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988 ...
- nowcoder 206A - Birthday - [最小费用最大流]
题目链接:https://www.nowcoder.com/acm/contest/206/A 题目描述 恬恬的生日临近了.宇扬给她准备了一个蛋糕.正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为 ...
随机推荐
- [创业中, 寻求合作] 业务方向:车联网智能终端;APP蓝牙控制汽车;APP网络远程控制汽车 (联系电话:18503086002)
擅长领域 手机APP蓝牙控制汽车方案 手机APP网络远程控制汽车方案 手机APP与汽车车机的文件极速传输技术 车载OBD终端 (后装) 智能TBOX终端,Base on Linux,使用车规级硬件加密 ...
- PHP 文件管理
主页面: <?php session_start(); $filename=""; if(!empty($_SESSION["lujing"])) { $ ...
- win7电脑怎么修改计算机用户名Administrator
----------------------------------- 首先,在开始中打开我的控制面板.----->>打开用户账户和家庭安全选项.----->>,继续点击用户账 ...
- u盘安装Fedora23
-2.计划用ultraiso安装 fedora 23 ,然后从windows平台转到Linux平台上. -1.概念理解 硬盘模式:achi(sata) ide (ata) 分区格式:主引导记录(mbr ...
- R包igraph探究
前段时候由于项目的原因,需要画图,然后开始接触R语言的igraph包,网上零零散散的搜罗了不少的信息,放在这边交流分享的同时也给自己留个备份吧~ 1.首先是读取文件,基本选用的都是csv文件 edge ...
- Linux线程同步:条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
- CentOS6.3 编译安装LAMP(4):编译安装 PHP5.3.27
所需源码包: /usr/local/src/PHP-5.3.27/libmcrypt-2.5.8.tar.gz /usr/local/src/PHP-5.3.27/mhash-0.9.9.9.tar. ...
- 转:浅谈UNIX下Apache的MPM及httpd.conf配置文件中相关参数配置
为什么要并发处理 以Apache为代表的web服务器中,如果不支持并发,则在一个客户端连接的时候,如果该客户端的任务没有处理完,其他连接的客户端将会一直处于等待状态,这事不可想象的,好像没有为什么要不 ...
- appium for mobile web 之使用 ChromeDriver
之前研究了一段时间的appium for native app 相应的总结如下: appium测试环境搭建 :ht ...
- .NET 面向对象基础
封装 ...