CodeForces-919D Substring DP,拓扑排序
给定一个有 n 个节点和 m 条有向边的图。每个节点上有一个小写字母。
我们将路径的值定义为最经常出现的字母的数目。例如,如果路径上的字母是 “abaca”,那么该路径的值是 3。
你的任务是找到一条值最大的路径,并将这条路径的值输出。
显然条件是必须在一条路径上,容易想到限制要求拓扑排序,因此可以在拓扑序上DP
dp[i][j]表示前i个点中,字母j出现的次数。
int n, m, u, v; int num; queue<int> q; int dp[300005][27]; int Indeg[300005]; char s[300005]; vector<int> vec[300005]; bool topo() { while (!q.empty()) q.pop(); num = 0; for (int i = 1; i <= n; i++) if (!Indeg[i]) { q.push(i); dp[i][s[i] - 'a']++; } while (!q.empty()) { int now = q.front(); q.pop(); num++; for (int i = 0; i < vec[now].size(); i++) { if (--Indeg[vec[now][i]] == 0) { q.push(vec[now][i]); } for (int j = 0; j < 26; j++) { dp[vec[now][i]][j] = max(dp[vec[now][i]][j], dp[now][j] + (s[vec[now][i]] - 'a' == j)); } } } if (n == num) return true; else return false; } int main() { n = readint(); m = readint(); scanf("%s", s + 1); for (int i = 0; i < m; i++) { int x = readint(); int y = readint(); vec[x].push_back(y); Indeg[y]++; } if (!topo()) puts("-1"); else { int Max = -1; for (int i = 1; i <= n; i++) { for (int j = 0; j < 26; j++) { Max = max(Max, dp[i][j]); } } Put(Max); } }