用给的模式串build一个ac自动机
然后在fail树上做一个背包dp
dp[i][j]表示第i个状态下花费了 j 获得的最大价值
(顺便升级了一下原来的ac自动机模版)
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <queue>
#include <cstdio>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <cstring>
#include <cmath>
#include <vector>
#include <ctime>
#include <bitset>
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d\n",ans)
#define lansn() printf("%lld\n",ans)
#define r0(i,n) for(int i=0;i<(n);++i)
#define r1(i,e) for(int i=1;i<=e;++i)
#define rn(i,e) for(int i=e;i>=1;--i)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define lowbit(a) (a&(-a))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp(aa,bb) make_pair(aa,bb)
#define lrt rt<<1
#define rrt rt<<1|1
#define X first
#define Y second
#define PI (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//const ll mod = 1000000007 ;
const double eps=1e-9;
const int inf=0x3f3f3f3f;
//const ll infl = 100000000000000000;//1e17
const int maxn= 1e5+20;
const int maxm = 5e2+20;
//muv[i]=(p-(p/i))*muv[p%i]%p;
int in(int &ret) {
char c;
int sgn ;
if(c=getchar(),c==EOF)return -1;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret *=sgn;
return 1;
}
int ch[maxn][26];
int val[maxn],f[maxn],last[maxn];
int dp[maxn][222];
int sz;
void trie() {
sz=1;
mst(ch[0],-1);
}
void triein(char *s,int v) {
int u=0,n=strlen(s);
for(int i=0; i<n; ++i) {
int c=s[i]-'A';
if(ch[u][c]==-1) {
mst(ch[sz],-1);
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]+=v;
}
void build() {
f[0]=0;
queue<int>q;
for(int c=0; c<26; ++c) {
int u=ch[0][c];
if(u==-1) {
ch[0][c] = 0;
continue;
}
q.push(u);
f[u]=0;
// last[u]=0;
}
while(!q.empty()) {
int r=q.front();
q.pop();
for(int c=0; c<26; ++c) {
int u=ch[r][c];
if(u==-1) {
ch[r][c] = ch[f[r]][c];
continue;
}
q.push(u);
int v=f[r];
// while(v&&!ch[v][c])v=f[v];
f[u]=ch[v][c];
// last[u]= val[ f[u] ] ? f[u] : last[f[u]];
val[u] += val[f[u]];
}
}
}
vector<pii>v;
char s[maxn];
int k;
int n,m;
int ans = 0;
void cal() {
mst(dp,-1);
dp[0][0] = 0;
ans = 0;
for(int i=0; i<=k; ++i) {
for(int j=0; j<sz; ++j) {
ans = max(ans,dp[j][i]);
if(~dp[j][i])
for(int w = 0; w<n; ++w) {
int u = v[w].X ;
int c = v[w].Y ;
int nt = ch[j][u];
if(nt>=0&&nt<sz&&i+c<=k)
dp[nt][i+c] = max(dp[nt][i+c] , dp[j][i] + val[nt]);
}
}
}
}
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int t;
sd(t);
r1(cas,t) {
printf("Case #%d: ",cas);
trie();
v.clear();
sddd(n,m,k);
r1(i,n) {
ss(s);
int x = s[0] - 'A';
int y;
sd(y);
v.pb(mp(x,y));
}
while(m--) {
ss(s);
int x;
sd(x);
triein(s,x);
}
build();
cal();
ansn();
}
return 0;
}