Petrozavodsk Winter Training Camp 2016: Moscow SU Trinity Contest( 二 )


Solution思路:? 树形dp维护以某个节点为根的子树中,以根为路径的一个端点,可以在$S$ 中匹配的最长前缀和后缀 。当某棵子树的前后缀已经覆盖了$S$,并且前后缀的路径不重复,就是合法路径 。保证不重复的方法详见代码 。
Codeint n, m, idx;string s;int head[maxn];pii st[maxn], ed[maxn], ans;struct Edge {int to, nxt; char c;} edge[maxn * 2];void addedge(int u, int v, char c) {edge[idx] = {v, head[u], c};head[u] = idx ++;edge[idx] = {u, head[v], c};head[v] = idx ++;}void dfs(int u, int fa) {st[u] = ed[u] = {0, u};for(int i = head[u]; ~i; i = edge[i].nxt) {int v = edge[i].to; char c = edge[i].c;if(v == fa) continue;dfs(v, u);if(c == s[st[v].x + 1] && st[v].x < m) st[v].x ++;if(c == s[m - ed[v].x] && ed[v].x < m) ed[v].x ++;// 路径不重复if(st[u].x + ed[v].x >= m) ans = {st[u].y, ed[v].y};if(ed[u].x + st[v].x >= m) ans = {st[v].y, ed[u].y};st[u] = max(st[u], st[v]);ed[u] = max(ed[u], ed[v]);}}int main() {ios;cin >> n >> m;for(int i = 1; i <= n; i ++) head[i] = -1;for(int i = 1; i < n; i ++) {int u, v; char c;cin >> u >> v >> c;addedge(u, v, c);}cin >> s;s = "?" + s;ans = {-1, -1};dfs(1, 0);cout << ans.x << " " << ans.y;}

经验总结扩展阅读