Codeforces 919D - Substring
思路:
拓扑排序判环+DAG上dp+记忆化搜索
状态:dp[i][j]表示以i为起点的路径中j的最大出现次数
初始状态:dp[i][j]=1(i have no son && w[i]==j)
dp[i][j]=0(i have no son && w[i]!=j)
状态转移:dp[i][j]=max(dp[t][j])(t is i's son)
dp[i][j]++(w[i]==j)
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=3e5+5; int head[N]; int w[N]; int in[N]; int tin[N]; int dp[N][26]; int cnt=0; struct edge{ int to,next; }edge[N]; void add_edge(int u,int v){ edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } bool topo_sort(int n){ queue<int>q; int cnt=0; for(int i=1;i<=n;i++)if(tin[i]==0)q.push(i),cnt++; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];~i;i=edge[i].next){ tin[edge[i].to]--; if(tin[edge[i].to]==0)q.push(edge[i].to),cnt++; } } return cnt>=n; } int dfs(int u,int x){ if(dp[u][x]!=-1)return dp[u][x]; dp[u][x]=0; for(int i=head[u];~i;i=edge[i].next){ dp[u][x]=max(dp[u][x],dfs(edge[i].to,x)); } if(w[u]==x)dp[u][x]++; return dp[u][x]; } int main(){ ios::sync_with_stdio(false); cin.tie(0); mem(head,-1); mem(dp,-1); int n,m,u,v; string s; cin>>n>>m; cin>>s; for(int i=0;i<s.size();i++)w[i+1]=s[i]-'a'; for(int i=0;i<m;i++)cin>>u>>v,add_edge(u,v),in[v]++,tin[v]++; if(topo_sort(n)){ int ans=0; for(int i=1;i<=n;i++){ if(in[i]==0){ for(int j=0;j<26;j++){ ans=max(ans,dfs(i,j)); } } } cout<<ans<<endl; } else cout<<-1<<endl; return 0; }