样例是能过的,但是交在SPOJ上会WA,看不到数据就很难受
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
const int maxn = 2e4 + 5;
const int maxs = 3e5 + 5;
int T, n, cur, ans, dfncnt;
int w[maxn], st[maxn], pos[maxn], dfn[maxs], sze[maxs];
char s[maxs];
struct edge {
int to, nxt;
} e[maxs];
int tot = 1, head[maxs];
void addedge(int u, int v) {
e[++tot].to = v;
e[tot].nxt = head[u];
head[u] = tot;
}
struct AcAutomaton {
int trietot;
int ch[maxs][26], fail[maxs];
void ins(char* p, int id) {
int len = strlen(p+1), now = 0;
for(int i = 1; i <= len; i++) {
int v = p[i]-'a';
if(!ch[now][v]) ch[now][v] = ++trietot;
now = ch[now][v];
}
pos[id] = now;
}
void build() {
std::queue<int> q;
for(int i = 0; i < 26; i++)
if(ch[0][i]) q.push(ch[0][i]), addedge(0, ch[0][i]);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0; i < 26; i++) {
int v = ch[u][i];
if(v) {
fail[v] = ch[fail[u]][i];
addedge(fail[v], v);
q.push(v);
}
else ch[u][i] = ch[fail[u]][i];
}
}
}
} ac;
struct SegmentTree {
#define ls (id << 1)
#define rs (id << 1 | 1)
#define mid ((l + r) >> 1)
int t[maxs<<2], lazy[maxn<<2];
void pushdown(int id) {
if(lazy[ls] < lazy[id]) {
t[ls] = std::max(t[ls], lazy[id]);
lazy[ls] = std::max(lazy[ls], lazy[id]);
}
if(lazy[rs] < lazy[id]) {
t[rs] = std::max(t[rs], lazy[id]);
lazy[rs] = std::max(lazy[rs], lazy[id]);
}
lazy[id] = 0;
}
void modify(int l, int r, int id, int ql, int qr, int val) {
if(ql <= l && r <= qr) {
t[id] = std::max(t[id], val);
lazy[id] = std::max(lazy[id], val);
return;
}
if(lazy[id] > val) return;
if(lazy[id]) pushdown(id);
if(ql <= mid) modify(l, mid, ls, ql, qr, val);
if(mid < qr) modify(mid+1, r, rs, ql, qr, val);
t[id] = std::max(t[ls], t[rs]);
}
int query(int l, int r, int id, int q) {
if(l == r) return t[id];
if(lazy[id]) pushdown(id);
if(q <= mid) return query(l, mid, ls, q);
else return query(mid+1, r, rs, q);
}
} seg;
void dfs(int u) {
dfn[u] = ++dfncnt;
sze[u] = 1;
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dfs(v);
sze[u] += sze[v];
}
}
int getans(char* p) {
int len = strlen(p+1), now = 0, res = 0;
for(int i = 1; i <= len; i++) {
int v = p[i]-'a';
now = ac.ch[now][v];
res = std::max(res, seg.query(1, dfncnt, 1, dfn[now]));
}
return res;
}
void clear() {
cur = -1;
ans = dfncnt = ac.trietot = 0;
tot = 1;
memset(head, 0, sizeof(head));
memset(e, 0, sizeof(e));
memset(ac.ch, 0, sizeof(ac.ch));
memset(ac.fail, 0, sizeof(ac.fail));
memset(seg.t, 0, sizeof(seg.t));
memset(seg.lazy, 0, sizeof(seg.lazy));
}
int main() {
scanf("%d", &T);
for(int F = 1; F <= T; F++) {
clear();
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%s", s+cur+2);
scanf("%d", &w[i]);
st[i] = cur+1;
ac.ins(s+cur+1, i);
cur += strlen(s+cur+2) + 1;
}
ac.build();
dfs(0);
for(int i = 1; i <= n; i++) {
int x = getans(s+st[i]) + w[i];
seg.modify(1, dfncnt, 1, dfn[pos[i]], dfn[pos[i]]+sze[pos[i]]-1, x);
ans = std::max(ans, x);
}
printf("Case #%d: %d\n", F, ans);
}
return 0;
}