Substring
题目传送门
题意:给你一个有向图,有n个点和m条边。每个点有一个小写字母字符。问该图中的所有路径中重复字符最多是多少,如果无穷大输出-1.
思路:很容易想到从入度为0点dfs所有路径取最大,但n非常大,简单的dfs会超时。可是,每个节点到其所有叶子节点的路径都是唯一的,只需dfs一遍即可。所以用dfs记忆化搜索,每一个节点用一个数组保存该节点到叶子节点的所有路径中每种字符的最大值。
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <algorithm>
#include <functional>
#define inf 10000000
using namespace std;
typedef long long ll;
const int MAXN=5e6+10;
const int MAX=3e5+10;
const double eps=1e-6;
int n,m,flag=1;
char s[MAX];
int du[MAX];
vector<int>G[MAX];
int save[MAX][30];
bool vis[MAX];
bool book[MAX];
int dfs(int node){
if(!flag) return -1;
save[node][0]=1;
for(int i=0;i<G[node].size();i++){
int v=G[node][i];
book[v]=1;
if(vis[v]){
flag=0;
return -1;
}
if(!save[v][0]){
vis[v]=1;
dfs(v);
vis[v]=0;
}
for(int j=1;j<=26;j++){
save[node][j]=max(save[node][j],save[v][j]);
}
}
save[node][s[node]-'a'+1]++;
int ans=-1;
for(int i=1;i<=26;i++){
ans=max(ans,save[node][i]);
}
return ans;
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
cin>>n>>m;
scanf("%s",s+1);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u==v) flag=0;
du[v]++;
G[u].push_back(v);
}
int ans=-1;
for(int i=1;i<=n;i++){
if(du[i]==0&&save[i][0]==0){
vis[i]=1;
book[i]=1;
ans=max(ans,dfs(i));
vis[i]=0;
}
}
for(int i=1;i<=n;i++){
if(!book[i]){
flag=0;
break;
}
}
if(flag)
cout<<ans<<endl;
else
cout<<-1<<endl;
return 0;
}