1. 程式人生 > 其它 >P7537 [COCI2016-2017#4] Rima

P7537 [COCI2016-2017#4] Rima

非常好的一道題!!!!

字典樹上的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));
}