【Codeforces717G】Underfail Hash + 最大费用最大流
G. Underfail
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.
Example
6
abacba
2
aba 6
ba 3
3
12
Note
For example, with the string "abacba", words "aba" (6 points) and "ba" (3 points), and x = 3, you can get at most 12 points - the word "aba" appears once ("abacba"), while "ba" appears two times ("abacba"). Note that for x = 1, you could get at most 9 points, since you wouldn’t be able to count both "aba" and the first appearance of "ba".
Solution
题目大意:给定一个长度为N的模板串,以及M个短串,每个短串有一个价值c,用一个短串完全匹配模板串的区间,可以得到短串的价值。每个短串可以匹配任意次,模板串的每个位置,只能匹配K次。求最大价值。
这道题还是比较容易想到的
首先把所有短串去和大串匹配,得到每个小串的完全匹配的区间。 然后套用费用流经典建图。
这个过程可以暴力,Hash,AC自动机,KMP...
然后对于这个区间$[l,r]$,我们连边$<l,r+1>,cap=1,cost=c$ ,这里连边$<l,r+1>$是控制区间左闭右开,否则会出现负环。
然后连$<S,1>,cap=K,cost=0$以及$<N,T>,cap=K,cost=0$ ,前一个位置向后一个位置连边$<i,i+1>,cap=K,cost=0$
然后跑$S->T$的最大费用最大流就是答案。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 510
int N,M,K,c[];
char s[MAXN],ss[][];
namespace Hash
{
#define base 131
#define ULL unsigned long long
ULL hash[MAXN],bin[MAXN];
void Hashtable()
{
bin[]=; for (int i=; i<=N; i++) bin[i]=bin[i-]*base;
for (int i=; i<=N; i++) hash[i]=hash[i-]*base+s[i];
}
ULL GetHash(int l,int r) {return hash[r]-hash[l-]*bin[r-l+];}
ULL Hashit(char st[])
{
ULL re=; int len=strlen(st+);
for (int i=; i<=len; i++) re=re*base+st[i];
return re;
}
}
using namespace Hash;
namespace CostFlow
{
#define INF 0x7fffffff
#define MAXM 100010
struct EdgeNode{int next,to,cap,cost,from;}edge[MAXM<<];
int head[MAXN],cnt=;
inline void AddEdge(int u,int v,int w,int c) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w; edge[cnt].cost=c; edge[cnt].from=u;}
inline void InsertEdge(int u,int v,int w,int c) {AddEdge(u,v,w,c); AddEdge(v,u,,-c);}
int S,T,Cost,dis[MAXN],visit[MAXN],mark[MAXN];
queue<int>q;
inline bool SPFA()
{
for (int i=S; i<=T; i++) dis[i]=-INF;
q.push(S); visit[S]=; dis[S]=;
while (!q.empty())
{
int now=q.front(); q.pop(); visit[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]<dis[now]+edge[i].cost)
{
dis[edge[i].to]=dis[now]+edge[i].cost;
if (!visit[edge[i].to]) q.push(edge[i].to),visit[edge[i].to]=;
}
}
return dis[T]!=-INF;
}
inline int dfs(int now,int low)
{
mark[now]=;
if (now==T) return low;
int w,used=;
for (int i=head[now]; i; i=edge[i].next)
if (!mark[edge[i].to] && edge[i].cap && dis[edge[i].to]==dis[now]+edge[i].cost)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w; Cost+=w*edge[i].cost; used+=w;
if (used==low) return low;
}
return used;
}
inline int zkw()
{
int re=;
while (SPFA())
{
mark[T]=;
while (mark[T])
memset(mark,,sizeof(mark)),re+=dfs(S,INF);
}
return re;
}
inline void BuildGraph()
{
S=,T=N+;
Hash::Hashtable();
InsertEdge(S,,K,); InsertEdge(N,T,K,);
for (int i=; i<=N-; i++) InsertEdge(i,i+,K,);
for (int i=; i<=M; i++)
{
ULL _hash=Hash::Hashit(ss[i]); int l=strlen(ss[i]+);
for (int j=; j+l-<=N; j++)
if (Hash::GetHash(j,j+l-)==_hash) InsertEdge(j,j+l,,c[i]);
}
// for (int i=2; i<=cnt; i+=2) printf("%d %d %d %d\n",edge[i].from,edge[i].to,edge[i].cap,edge[i].cost);
}
}
int main()
{
N=read(); scanf("%s",s+);
M=read();
for (int i=; i<=M; i++) scanf("%s",ss[i]+),c[i]=read();
K=read();
CostFlow::BuildGraph();
CostFlow::zkw();
printf("%d\n",CostFlow::Cost);
return ;
}
Codeforces上的数据真是太小了...这个题暴力都能跑的那么快...
【Codeforces717G】Underfail Hash + 最大费用最大流的更多相关文章
- Codeforces 717G Underfail(最小费用最大流 + AC自动机)
题目 Source http://codeforces.com/problemset/problem/717/G Description You have recently fallen throug ...
- [CODEVS1917] 深海机器人问题(最小费用最大流)
传送门 [问题分析] 最大费用最大流问题. [建模方法] 把网格中每个位置抽象成网络中一个节点,建立附加源S汇T. 1.对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点i与节点j一条容量为1, ...
- [板子]最小费用最大流(Dijkstra增广)
最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...
- bzoj1927最小费用最大流
其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→ =_=你TM逗我 刚要删突然感觉dinic的模 ...
- ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)
将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...
- HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...
- P3381 【模板】最小费用最大流
P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...
- 最小/大费用最大流模板(codevs1914)
void addedge(int fr,int to,int cap,int cos){ sid[cnt].fr=fr;sid[cnt].des=to;sid[cnt].cap=cap;sid[cnt ...
- 【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 726 Solved: 309[Submit][Status ...
随机推荐
- JavaWeb工程中web.xml基本配置
一.理论准备 先说下我记得xml规则,必须有且只有一个根节点,大小写敏感,标签不嵌套,必须配对. web.xml是不是必须的呢?不是的,只要你不用到里面的配置信息就好了,不过在大型web工程下使用该文 ...
- android 关闭/开启软件键盘(hideSoftKeyboard)
/** * 隐藏软键盘 * @param v */ public static void hideSoftKeyboard(View v) { InputMethodManager imm = (In ...
- 003.安装nginx(lnmp)
一.下载nginx 下载nginx源码包,解压: [root@huh ~]# cd /usr/local/src/ [root@huh src]# wget http://nginx.org/down ...
- Redis学习笔记1-Redis的介绍和认识
说明:文章内容来自百度百科和redis官方对redis的介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API ...
- Git版本控制常用命令整理
基础命令: git init 初始化一个空仓库 git add 添加已经修改的工作区文件 git add newmodifiedfile git commit -m "log conten ...
- 基于Fast Bilateral Filtering 算法的 High-Dynamic Range(HDR) 图像显示技术。
一.引言 本人初次接触HDR方面的知识,有描述不正确的地方烦请见谅. 为方便文章描述,引用部分百度中的文章对HDR图像进行简单的描述. 高动态范围图像(High-Dynamic Range,简称HDR ...
- java1.8函数式编程概念
有关函数式编程 ·1 函数作为一等公民 特点:将函数作为参数传递给另外一个函数:函数可以作为另外一个函数的返回值 ·2 无副作用 函数的副作用指的是函数在调用过程中,除了给出了返回值外,还修改了函数外 ...
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 总部业务部门主管管理整个集团分公司的某项业务
由于整个集团公司非常庞大,有上千个分支机构,不可能由总部某个人能管理所有的数据,或者掌握所有的业务.某个业务都会由于某个相应的部门进行管理,例如所有分公司的人力资源,都由总部的人力资源部门管理.哪些分 ...
- C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 数据权限增强、范围权限增强
并不是不想做B\S的管理工具,只是精力实在不够,由于用户权限管理组件是基础组件.所以C\S的也无妨,不会有几个人在乎Oracle,SQLServer是否不b\s的,注重的是功能性能,请大家不要纠结与是 ...
- WebApi2跨域问题
一.跨域问题产生的原因:同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能. 现在所有支持JavaScript 的浏览器都会使用这个策略. 所谓同源是指,域 ...