TopicsSource
Http://codeforces.com/problemset/problem/717/G
Description
You have recently fallen through a hole and, after several hours of unconsciousness, has realized you is in an Undergrou ND city. On one of your regular, daily walks through the unknown, you have encountered, unusually looking skeletons called Sanz and P ' Pairus, who decided to accompany you and give the some puzzles for seemingly unknown reasons.
One day, Sanz have created a crossword for you. Not all kind of crossword, but a 1D crossword! You are given m words and a string of length n. You were also given an array p, which designates how much each word was worth-the i-th word is worth pi points. Whenever you find one of the "words in the" string, you are given the corresponding number of points. Each position in the crossword can is used at a most x times. A certain word can be counted in 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-haven ' t used the positions more than X Ti MES).
In order to solve the puzzle, you need to tell Sanz "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 中文版 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'll has a string representing a non-empty word (its length doesn ' t exceed the length of the Crosswo RD) and Integer Pi (0≤pi≤100). Last line of the input would 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
Analysis
The topic probably says to a main string and several valuable pattern string, a pattern string matches with the main string to accumulate the corresponding value, a pattern string can match in many positions and the main string but only once, moreover the main string each character can use up to X times, asks how to match makes obtains the value biggest.
Each pattern string can be found in the matching position of the main string by an AC automaton, which is equivalent to the interval.
In fact, this problem is equivalent to the selection of the maximum right and the interval on a single axis, so that the number of each point is covered by no more than X. Interval k coverage problem, POJ3680.
I can't even build a map. It is important to note that the interval is to be processed to the left-hand open form, otherwise, such as [the] area of the map will appear negative ring.
Code
#include <cstdio> #include <cstring> #include <queue> #include <algorithm>using namespace std;# Define INF (1<<30) #define MAXN 555#define maxm 555*1111struct 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);p rintf ("%d",-MCMF ()); return 0;}
Codeforces 717G underfail (minimum charge max flow + AC automaton)