D. Substring
题意:
给你一个有向图,然后给你一串字符串第i个点的值为第i个字符,然后给你m条有向边,从中找一条路径然后这条路径中点的值相同的个数的最大值,如果图有环输出-1。
思路:
拓扑排序+dp
我们需要找到一条路径的开头,用拓扑排序即可,然后每个点维护26个字母在到当前点的路径上出现最大值即可,复杂度O(n*26)。
题链
代码:
#include<bits/stdc++.h>
using namespace std;
int dp[300005][26];
class Solution
{
public:
int n,m;
char str[300005];
int cnt[300005];
vector<int>vec[300005];
queue<int>que;
map<pair<int,int>,int>my;
Solution()
{
memset(str,0,sizeof(str));
memset(cnt,0,sizeof(cnt));
for(int i = 0; i < 300005; i++)
vec[i].clear();
while(!que.empty())
{
que.pop();
}
}
void in_put()
{
scanf("%d %d",&n,&m);
scanf("%s",str);
for(int i = 0; i < m; i++)
{
int x,y;
scanf("%d %d",&x,&y);
if(!my.count(make_pair(x,y)))
{
my[make_pair(x,y)] = 1;
cnt[y]++;
vec[x].push_back(y);
}
}
}
int TUPU()
{
int maxx = -1;
int cn = 0;
for(int i = 1; i <= n; i++)
{
if(cnt[i] == 0)
{
que.push(i);
dp[i][str[i-1] - 'a'] = 1;
maxx = 1;
cn++;
}
}
while(!que.empty())
{
int id = que.front();
que.pop();
for(int i = 0; i < vec[id].size(); i++)
{
int ic = vec[id][i];
for(int j = 0; j < 26; j++)
{
if(j == str[ic - 1] - 'a')
dp[ic][j] = max(dp[ic][j],dp[id][j] + 1);
else dp[ic][j] = max(dp[ic][j],dp[id][j]);
// printf("%d %d %d\n",id,maxx,ic);
maxx = max(dp[ic][j],maxx);
}
cnt[ic]--;
if(cnt[ic] == 0)
cn++,que.push(ic);
}
}
if(cn == n)
return maxx;
return -1;
}
};
int main(void)
{
Solution A;
A.in_put();
cout<<A.TUPU();
return 0;
}