P7537 [COCI2016-2017#4] Rima
阿新 • • 發佈:2022-04-01
非常好的一道題!!!!
字典樹上的dp題目
首先建立字典樹
開始我理解錯了 以為只要樹上的1是連續的就滿足 於是就打了個56分 樹上的最大連續和
出題人還是比較好 這樣的情況都有56分 實際情況是
就是從高到低再到高這個情況
問題很明顯就變成了維護最大值和次大值(更新最大值的時候一定要先更新次大值)
ans就是 最大+次大+其他臨近節點+本身 (注意這裡臨近節點是指直接相連的親兒子!)
dp[u]表示u的子樹裡面到u的最大值 根節點要特判
只有num[u]!=0 即有以u節點結束的單詞才更新dp[u] 因為連續性肯定是要保證的
在每個節點更新ans 不管num[u]是否等於0
比如 hais 和 pais 這兩個肯定是成立的 但是num[a]是等於0的
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int maxn=3e6+5; int tr[maxn][26],dp[maxn],num[maxn]; int n,cnt,ans; string s,t; void insert(string ss); void dfs(int u); int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>s; t=s; int len=s.size(); for(int j=0;j<len;j++) t[j]=s[len-j-1]; insert(t); } dfs(0); cout<<ans<<endl; return 0; } void insert(string ss){ int root=0; for(int i=0;i<ss.size();i++){ int id=ss[i]-'a'; if(!tr[root][id])tr[root][id]=++cnt; root=tr[root][id]; } num[root]++; } void dfs(int u){ int max1=0,max2=0,res=0; for(int i=0;i<26;i++){ int to=tr[u][i]; if(!to)continue; dfs(to);res+=num[to]; if(dp[to]>max1){ max2=max1; max1=dp[to]; } else if(dp[to]>max2)max2=dp[to]; } if(num[u]){ if(!res)dp[u]=1; else dp[u]=max1+res; } ans=max(ans,max1+max2+num[u]+max(res-2,0)); }