Codeforces Gym100962J:Jimi Hendrix(树型DP)

http://codeforces.com/gym/100962/attachments

题意:有一个n个节点的字母树,给出n-1条边的信息,代表边上有一个字母,然后给出长度为m的字符串,问是否能在这棵树上找到这样一个序列等于这条字符串,输出序列的起点和终点。

思路:用DP数组维护当到达该结点的时候,左边最长的长度是多少和达到这个长度的左端点,右边最长的长度是多少和达到这个长度的右端点。详细看代码,很容易懂。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 500010
 4 struct Edge {
 5     int v, nxt; char c;
 6 } edge[N*2];
 7 struct node {
 8     int l, r, ansl, ansr;
 9 } dp[N]; // l是保存头,r是保存尾的信息
10 int tot, head[N], n, m, ansu, ansv;
11 char s[N];
12 
13 void Add(int u, int v, char c) {
14     edge[tot] = (Edge) {v, head[u], c}; head[u] = tot++;
15     edge[tot] = (Edge) {u, head[v], c}; head[v] = tot++;
16 }
17 
18 bool dfs(int u, int fa) {
19     for(int i = head[u]; ~i; i = edge[i].nxt) {
20         int v = edge[i].v; char c = edge[i].c;
21         if(v == fa) continue;
22         if(dfs(v, u)) return true; // 已经有答案了
23         int ltmp = dp[v].l;
24         int rtmp = dp[v].r;
25         if(c == s[dp[v].l]) ltmp++; // 如果当前的边是左边的下一个字符
26         if(c == s[m - dp[v].r - 1]) rtmp++; // 如果当前的边是右边的下一个字符
27         if(ltmp + dp[u].r >= m) { // 有答案了
28             ansu = dp[v].ansl, ansv = dp[u].ansr;
29             return true;
30         }
31         if(dp[u].l + rtmp >= m) {
32             ansu = dp[u].ansl, ansv = dp[v].ansr;
33             return true;
34         }
35         if(ltmp > dp[u].l) { // 如果长度变长就更新
36             dp[u].ansl = dp[v].ansl;
37             dp[u].l = ltmp;
38         }
39         if(rtmp > dp[u].r) {
40             dp[u].ansr = dp[v].ansr;
41             dp[u].r = rtmp;
42         }
43     }
44     return false;
45 }
46 
47 int main() {
48     scanf("%d%d", &n, &m);
49     tot = 0; memset(head, -1, sizeof(head));
50     for(int i = 1; i < n; i++) {
51         int u, v; char c;
52         cin >> u >> v >> c;
53         Add(u, v, c);
54         dp[i].l = dp[i].r = 0; // 点的信息
55         dp[i].ansl = dp[i].ansr = i; // 端点答案的信息
56     }
57     dp[n].l = dp[n].r = 0;
58     dp[n].ansl = dp[n].ansr = n;
59     cin >> s;
60     ansu = ansv = -1;
61     dfs(1, -1);
62     printf("%d %d
", ansu, ansv);
63     return 0;
64 }
原文地址:https://www.cnblogs.com/fightfordream/p/6423867.html