1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
#include <vector> #include <algorithm> const int MAXN = 100005; const int CHAR_SET = 10; struct { struct Node { int c[CHAR_SET], next; int max; Node() : max(0), next(-1) { std::fill(c, c + CHAR_SET, -1); } } N[MAXN * 40]; int start, nodeCnt; SuffixAutomaton() { init(); } void init() { start = 0; nodeCnt = 1; } int getMin(int u) { return N[N[u].next].max + 1; } int extend(int v, int c) { if (N[v].c[c] != -1 && N[N[v].c[c]].max == N[v].max + 1) return N[v].c[c]; int u = nodeCnt++; N[u].max = N[v].max + 1; while (v != -1 && N[v].c[c] == -1) { N[v].c[c] = u; v = N[v].next; } if (v == -1) { N[u].next = start; } else if (N[N[v].c[c]].max == N[v].max + 1) { N[u].next = N[v].c[c]; } else { int n = nodeCnt++, o = N[v].c[c]; N[n].max = N[v].max + 1; std::copy(N[o].c, N[o].c + CHAR_SET, N[n].c); N[n].next = N[o].next; N[o].next = N[u].next = n; for (; v != -1 && N[v].c[c] == o; v = N[v].next) N[v].c[c] = n; } return u; } long long calc() { long long res = 0; for (int p = 1; p != nodeCnt; p++) res += N[p].max - getMin(p) + 1; return res; } } sam; struct Edge; struct Node { Edge *e; int c, deg; } N[MAXN]; struct Edge { Node *u, *v; Edge *next; Edge() {} Edge(Node *u, Node *v) : u(u), v(v), next(u->e) {} } _pool[MAXN << 1], *_curr = _pool; void addEdge(int u, int v) { N[u].e = new (_curr++) Edge(&N[u], &N[v]); N[v].e = new (_curr++) Edge(&N[v], &N[u]); N[u].deg++; N[v].deg++; } void dfs(Node *u, Node *fa, int last) { int v = sam.extend(last, u->c); for (Edge *e = u->e; e; e = e->next) if (e->v != fa) dfs(e->v, u, v); } int main() { int n; scanf("%d %*d", &n); for (int i = 1; i <= n; i++) scanf("%d", &N[i].c); for (int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); addEdge(u, v); } for (int i = 1; i <= n; i++) if (N[i].deg == 1) dfs(&N[i], NULL, sam.start); printf("%lldn", sam.calc()); return 0; }
|
近期评论