[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3926
[算法]
建立广义后缀自动机
对于每个叶子节点 , 以它为根 , 依次将路径上的子串加入自动机
最后统计本质不同的子串个数即可
时间复杂度 : O(N)
[代码]
#include<bits/stdc++.h> using namespace std; const int N = 2e6 + 10; typedef long long ll; typedef long double ld; typedef unsigned long long ull; int n , m; int val[N]; vector< int > a[N]; struct Suffix_Automaton { int size; int father[N << 1] , child[N << 1][15] , depth[N << 1]; Suffix_Automaton() { size = 1; } inline int new_node(int dep) { depth[++size] = dep; memset(child[size] , 0 , sizeof(child[size])); father[size] = 0; return size; } inline int extend(int last , int ch) { int np = child[last][ch]; if (np) { if (depth[np] == depth[last] + 1) return np; else { int nq = new_node(depth[last] + 1); father[nq] = father[np]; father[np] = nq; memcpy(child[nq], child[np], sizeof(child[np])); for (int p = last; child[p][ch] == np; p = father[p]) child[p][ch] = nq; return nq; } } else { np = new_node(depth[last] + 1); int p = last; for (; child[p][ch] == 0; p = father[p]) child[p][ch] = np; if (child[p][ch] == np) { father[np] = 1; return np; } int q = child[p][ch]; if (depth[p] + 1 == depth[q]) { father[np] = q; return np; } else { int nq = new_node(depth[p] + 1); father[nq] = father[q]; father[q] = father[np] = nq; memcpy(child[nq], child[q], sizeof(child[q])); for (; child[p][ch] == q; p = father[p]) child[p][ch] = nq; return np; } } } inline ll calc() { ll ans = 0; for (int i = 2; i <= size; i++) ans += depth[i] - depth[father[i]]; return ans; } } SAM; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void dfs(int u , int par , int pre) { pre = SAM.extend(pre , val[u]); for (unsigned i = 0; i < a[u].size(); i++) { int v = a[u][i]; if (v != par) dfs(v , u , pre); } } int main() { read(n); read(m); for (int i = 1; i <= n; i++) read(val[i]); for (int i = 1; i < n; i++) { int x , y; read(x); read(y); a[x].push_back(y); a[y].push_back(x); } for (int i = 1; i <= n; i++) if (a[i].size() == 1) dfs(i , 0 , 1); printf("%lld " , SAM.calc()); return 0; }