#include <bits/stdc++.h>
using namespace std;
//
const int mnum = 1e5 + 5;
const int maxn = 3e5 + 5;
//
int n, m, p[maxn];
string s[maxn];
//
namespace Trie
{
struct Node
{
int cnt;
long long val;
Node *par, *child[26];
//
Node (void) : cnt(0), val(0)
{
fill(child, child + 26, nullptr);
}
};
//
Node *root = new Node();
Node *en[maxn];
//
void insert (int id)
{
int c;
Node *p = root;
//
for (char f : s[id])
{
c = f - 'A';
if (p->child[c] == nullptr)
p->child[c] = new Node(),
p->child[c]->par = p;
p = p->child[c];
++p->cnt;
}
en[id] = p;
}
void erase (int id, long long v)
{
Node *temp, *p = en[id];
//
while (p != root)
{
temp = p->par;
if (--p->cnt == 0)
delete(p);
p = temp;
p->val = max(p->val, v);
}
}
}
//
int check_sub (void)
{
int mx = 0;
//
for (int i = 1; i <= n; ++i)
mx = max(mx, (int)s[i].length());
if (n <= 100 && mx <= 100 && m <= 100)
return 1;
if (m == 0)
return 2;
return 3;
}
namespace subtask_1
{
vector<int> lucky[mnum];
long long dp[maxn];
//
void solve (void)
{
for (int u, v; m--;)
cin >> u >> v,
lucky[u].emplace_back(v),
lucky[v].emplace_back(u);
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j < i; ++j)
if (s[j].size() > s[i].size() && s[j].substr(0, s[i].size()) == s[i])
dp[i] = max(dp[i], dp[j]);
for (int x : lucky[p[i]])
for (int j = 1; j < i; ++j)
if (p[j] == x)
dp[i] = max(dp[i], dp[j]);
dp[i] += p[i];
}
cout << *max_element(dp + 1, dp + n + 1);
}
}
namespace subtask_2
{
void solve (void)
{
long long temp, ans = 0;
//
for (int i = 1; i <= n; ++i)
Trie::insert(i);
for (int i = 1; i <= n; ++i)
temp = Trie::en[i]->val + p[i],
ans = max(ans, temp),
Trie::erase(i, temp);
cout << ans;
}
}
namespace subtask_3
{
const int orz = 500;
//
vector<int> lucky[mnum];
vector<int> heavy[mnum];
long long num[mnum], lazy[mnum];
//
void build (void)
{
for (int u = 1; u < mnum; ++u)
for (int v : lucky[u])
if (lucky[v].size() > orz)
heavy[u].emplace_back(v);
}
void update (int u, long long val)
{
lazy[u] = val;
if (lucky[u].size() <= orz)
for (int v : lucky[u])
num[v] = max(num[v], lazy[u]);
}
long long get (int u)
{
long long res = num[u];
//
for (int v : heavy[u])
res = max(res, lazy[v]);
return res;
}
//
void solve (void)
{
long long temp, ans = 0;
//
for (int u, v; m--;)
cin >> u >> v,
lucky[u].emplace_back(v),
lucky[v].emplace_back(u);
build();
for (int i = 1; i <= n; ++i)
Trie::insert(i);
for (int i = 1; i <= n; ++i)
{
temp = max(Trie::en[i]->val, get(p[i])) + p[i];
ans = max(ans, temp);
Trie::erase(i, temp);
update(p[i], temp);
}
cout << ans;
}
}
//
void process (void)
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> s[i] >> p[i];
//
int sub = check_sub();
//
if (sub == 1)
return subtask_1::solve();
if (sub == 2)
return subtask_2::solve();
subtask_3::solve();
}
//
signed main (void)
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
process();
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Ci8vCmNvbnN0IGludCBtbnVtID0gMWU1ICsgNTsKY29uc3QgaW50IG1heG4gPSAzZTUgKyA1OwovLwppbnQgbiwgbSwgcFttYXhuXTsKc3RyaW5nIHNbbWF4bl07Ci8vCm5hbWVzcGFjZSBUcmllCnsKICAgIHN0cnVjdCBOb2RlCiAgICB7CiAgICAgICAgaW50IGNudDsKICAgICAgICBsb25nIGxvbmcgdmFsOwogICAgICAgIE5vZGUgKnBhciwgKmNoaWxkWzI2XTsKICAgICAgICAvLwogICAgICAgIE5vZGUgKHZvaWQpIDogY250KDApLCB2YWwoMCkKICAgICAgICB7CiAgICAgICAgICAgIGZpbGwoY2hpbGQsIGNoaWxkICsgMjYsIG51bGxwdHIpOwogICAgICAgIH0KICAgIH07CiAgICAvLwogICAgTm9kZSAqcm9vdCA9IG5ldyBOb2RlKCk7CiAgICBOb2RlICplblttYXhuXTsKICAgIC8vCiAgICB2b2lkIGluc2VydCAoaW50IGlkKQogICAgewogICAgICAgIGludCBjOwogICAgICAgIE5vZGUgKnAgPSByb290OwogICAgICAgIC8vCiAgICAgICAgZm9yIChjaGFyIGYgOiBzW2lkXSkKICAgICAgICB7CiAgICAgICAgICAgIGMgPSBmIC0gJ0EnOwogICAgICAgICAgICBpZiAocC0+Y2hpbGRbY10gPT0gbnVsbHB0cikKICAgICAgICAgICAgICAgIHAtPmNoaWxkW2NdID0gbmV3IE5vZGUoKSwKICAgICAgICAgICAgICAgIHAtPmNoaWxkW2NdLT5wYXIgPSBwOwogICAgICAgICAgICBwID0gcC0+Y2hpbGRbY107CiAgICAgICAgICAgICsrcC0+Y250OwogICAgICAgIH0KICAgICAgICBlbltpZF0gPSBwOwogICAgfQogICAgdm9pZCBlcmFzZSAoaW50IGlkLCBsb25nIGxvbmcgdikKICAgIHsKICAgICAgICBOb2RlICp0ZW1wLCAqcCA9IGVuW2lkXTsKICAgICAgICAvLwogICAgICAgIHdoaWxlIChwICE9IHJvb3QpCiAgICAgICAgewogICAgICAgICAgICB0ZW1wID0gcC0+cGFyOwogICAgICAgICAgICBpZiAoLS1wLT5jbnQgPT0gMCkKICAgICAgICAgICAgICAgIGRlbGV0ZShwKTsKICAgICAgICAgICAgcCA9IHRlbXA7CiAgICAgICAgICAgIHAtPnZhbCA9IG1heChwLT52YWwsIHYpOwogICAgICAgIH0KICAgIH0KfQovLwppbnQgY2hlY2tfc3ViICh2b2lkKQp7CiAgICBpbnQgbXggPSAwOwogICAgLy8KICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG47ICsraSkKICAgICAgICBteCA9IG1heChteCwgKGludClzW2ldLmxlbmd0aCgpKTsKICAgIGlmIChuIDw9IDEwMCAmJiBteCA8PSAxMDAgJiYgbSA8PSAxMDApCiAgICAgICAgcmV0dXJuIDE7CiAgICBpZiAobSA9PSAwKQogICAgICAgIHJldHVybiAyOwogICAgcmV0dXJuIDM7Cn0KbmFtZXNwYWNlIHN1YnRhc2tfMQp7CiAgICB2ZWN0b3I8aW50PiBsdWNreVttbnVtXTsKICAgIGxvbmcgbG9uZyBkcFttYXhuXTsKICAgIC8vCiAgICB2b2lkIHNvbHZlICh2b2lkKQogICAgewogICAgICAgIGZvciAoaW50IHUsIHY7IG0tLTspCiAgICAgICAgICAgIGNpbiA+PiB1ID4+IHYsCiAgICAgICAgICAgIGx1Y2t5W3VdLmVtcGxhY2VfYmFjayh2KSwKICAgICAgICAgICAgbHVja3lbdl0uZW1wbGFjZV9iYWNrKHUpOwoKICAgICAgICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpCiAgICAgICAgewogICAgICAgICAgICBmb3IgKGludCBqID0gMTsgaiA8IGk7ICsraikKICAgICAgICAgICAgICAgIGlmIChzW2pdLnNpemUoKSA+IHNbaV0uc2l6ZSgpICYmIHNbal0uc3Vic3RyKDAsIHNbaV0uc2l6ZSgpKSA9PSBzW2ldKQogICAgICAgICAgICAgICAgICAgIGRwW2ldID0gbWF4KGRwW2ldLCBkcFtqXSk7CiAgICAgICAgICAgIGZvciAoaW50IHggOiBsdWNreVtwW2ldXSkKICAgICAgICAgICAgICAgIGZvciAoaW50IGogPSAxOyBqIDwgaTsgKytqKQogICAgICAgICAgICAgICAgICAgIGlmIChwW2pdID09IHgpCiAgICAgICAgICAgICAgICAgICAgICAgIGRwW2ldID0gbWF4KGRwW2ldLCBkcFtqXSk7CiAgICAgICAgICAgIGRwW2ldICs9IHBbaV07CiAgICAgICAgfQoKICAgICAgICBjb3V0IDw8ICptYXhfZWxlbWVudChkcCArIDEsIGRwICsgbiArIDEpOwogICAgfQp9Cm5hbWVzcGFjZSBzdWJ0YXNrXzIKewogICAgdm9pZCBzb2x2ZSAodm9pZCkKICAgIHsKICAgICAgICBsb25nIGxvbmcgdGVtcCwgYW5zID0gMDsKICAgICAgICAvLwogICAgICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG47ICsraSkKICAgICAgICAgICAgVHJpZTo6aW5zZXJ0KGkpOwogICAgICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG47ICsraSkKICAgICAgICAgICAgdGVtcCA9IFRyaWU6OmVuW2ldLT52YWwgKyBwW2ldLAogICAgICAgICAgICBhbnMgPSBtYXgoYW5zLCB0ZW1wKSwKICAgICAgICAgICAgVHJpZTo6ZXJhc2UoaSwgdGVtcCk7CiAgICAgICAgY291dCA8PCBhbnM7CiAgICB9Cn0KbmFtZXNwYWNlIHN1YnRhc2tfMwp7CiAgICBjb25zdCBpbnQgb3J6ID0gNTAwOwogICAgLy8KICAgIHZlY3RvcjxpbnQ+IGx1Y2t5W21udW1dOwogICAgdmVjdG9yPGludD4gaGVhdnlbbW51bV07CiAgICBsb25nIGxvbmcgbnVtW21udW1dLCBsYXp5W21udW1dOwogICAgLy8KICAgIHZvaWQgYnVpbGQgKHZvaWQpCiAgICB7CiAgICAgICAgZm9yIChpbnQgdSA9IDE7IHUgPCBtbnVtOyArK3UpCiAgICAgICAgICAgIGZvciAoaW50IHYgOiBsdWNreVt1XSkKICAgICAgICAgICAgICAgIGlmIChsdWNreVt2XS5zaXplKCkgPiBvcnopCiAgICAgICAgICAgICAgICAgICAgaGVhdnlbdV0uZW1wbGFjZV9iYWNrKHYpOwogICAgfQogICAgdm9pZCB1cGRhdGUgKGludCB1LCBsb25nIGxvbmcgdmFsKQogICAgewogICAgICAgIGxhenlbdV0gPSB2YWw7CiAgICAgICAgaWYgKGx1Y2t5W3VdLnNpemUoKSA8PSBvcnopCiAgICAgICAgICAgIGZvciAoaW50IHYgOiBsdWNreVt1XSkKICAgICAgICAgICAgICAgIG51bVt2XSA9IG1heChudW1bdl0sIGxhenlbdV0pOwogICAgfQogICAgbG9uZyBsb25nIGdldCAoaW50IHUpCiAgICB7CiAgICAgICAgbG9uZyBsb25nIHJlcyA9IG51bVt1XTsKICAgICAgICAvLwogICAgICAgIGZvciAoaW50IHYgOiBoZWF2eVt1XSkKICAgICAgICAgICAgcmVzID0gbWF4KHJlcywgbGF6eVt2XSk7CiAgICAgICAgcmV0dXJuIHJlczsKICAgIH0KICAgIC8vCiAgICB2b2lkIHNvbHZlICh2b2lkKQogICAgewogICAgICAgIGxvbmcgbG9uZyB0ZW1wLCBhbnMgPSAwOwogICAgICAgIC8vCiAgICAgICAgZm9yIChpbnQgdSwgdjsgbS0tOykKICAgICAgICAgICAgY2luID4+IHUgPj4gdiwKICAgICAgICAgICAgbHVja3lbdV0uZW1wbGFjZV9iYWNrKHYpLAogICAgICAgICAgICBsdWNreVt2XS5lbXBsYWNlX2JhY2sodSk7CgogICAgICAgIGJ1aWxkKCk7CiAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgKytpKQogICAgICAgICAgICBUcmllOjppbnNlcnQoaSk7CiAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgKytpKQogICAgICAgIHsKICAgICAgICAgICAgdGVtcCA9IG1heChUcmllOjplbltpXS0+dmFsLCBnZXQocFtpXSkpICsgcFtpXTsKICAgICAgICAgICAgYW5zID0gbWF4KGFucywgdGVtcCk7CiAgICAgICAgICAgIFRyaWU6OmVyYXNlKGksIHRlbXApOwogICAgICAgICAgICB1cGRhdGUocFtpXSwgdGVtcCk7CiAgICAgICAgfQoKICAgICAgICBjb3V0IDw8IGFuczsKICAgIH0KfQovLwp2b2lkIHByb2Nlc3MgKHZvaWQpCnsKICAgIGNpbiA+PiBuID4+IG07CiAgICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpCiAgICAgICAgY2luID4+IHNbaV0gPj4gcFtpXTsKICAgIC8vCiAgICBpbnQgc3ViID0gY2hlY2tfc3ViKCk7CiAgICAvLwogICAgaWYgKHN1YiA9PSAxKQogICAgICAgIHJldHVybiBzdWJ0YXNrXzE6OnNvbHZlKCk7CiAgICBpZiAoc3ViID09IDIpCiAgICAgICAgcmV0dXJuIHN1YnRhc2tfMjo6c29sdmUoKTsKICAgIHN1YnRhc2tfMzo6c29sdmUoKTsKfQovLwpzaWduZWQgbWFpbiAodm9pZCkKewogICAgaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSksIGNpbi50aWUobnVsbHB0ciksIGNvdXQudGllKG51bGxwdHIpOwogICAgcHJvY2VzcygpOwp9Cg==