建个AC自动机求个fail指针就好啦。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 1e5 + 7; const int M = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); int n, a[N]; string s[N]; struct Ac { int ch[N][26], val[N], f[N], mx[N], depth[N], deg[N], tot, sz; inline int newNode() { tot++; f[tot] = 0; val[tot] = 0; mx[tot] = 0, deg[tot] = 0; memset(ch[tot], 0, sizeof(ch[tot])); return tot; } void init(int _sz) {sz = _sz; tot = -1; newNode();} inline int idx(int c) {return c - 'a';} void addStr(string& s, int *a) { int u = 0; for(int i = 0; i < s.size(); i++) { int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = newNode(); u = ch[u][c]; val[u]++; depth[u] = i + 1; mx[u] = max(mx[u], a[i]); } } void build() { queue<int> que; for(int c = 0; c < sz; c++) { int v = ch[0][c]; if(!v) ch[0][c] = 0; else f[v] = 0, que.push(v); } while(!que.empty()) { int u = que.front(); que.pop(); for(int c = 0; c < sz; c++) { int v = ch[u][c]; if(!v) ch[u][c] = ch[f[u]][c]; else f[v] = ch[f[u]][c], deg[f[u]]++, que.push(v); } } } void solve() { init(26); cin >> n; for(int i = 1; i <= n; i++) cin >> s[i]; for(int i = 1; i <= n; i++) { for(int j = 0; j < s[i].size(); j++) cin >> a[j]; addStr(s[i], a); } build(); queue<int> que; for(int i = 1; i <= tot; i++) if(!deg[i]) que.push(i); while(!que.empty()) { int u = que.front(); que.pop(); mx[f[u]] = max(mx[f[u]], mx[u]); deg[f[u]]--; if(!deg[f[u]]) que.push(f[u]); } LL ans = 0; for(int i = 1; i <= tot; i++) ans = max(ans, 1ll*val[i]*mx[i]*depth[i]); cout << ans << " "; } } ac; int main() { freopen("exciting.in", "r", stdin); int T; scanf("%d", &T); while(T--) { ac.solve(); } return 0; } /* */