首页 > 其他分享 > Codeforces Round #837 (Div. 2)D (最大回文字串+树)

Codeforces Round #837 (Div. 2)D (最大回文字串+树)

时间:2022-12-12 13:46:59浏览次数:75  
标签:return 837 int res 文字串 Codeforces nex cal

题目链接:D. Hossam and (sub-)palindromic tree


题目描述

给定一颗有n(n<=2e3)个顶点的树,每个顶点有一个点权(字符),定义s(u,v)为从u到v的简单路径
所经过的点权形成的字符串的最大回文字串
求对于所有s(u,v)求最大回文子串


解题思路:

首先我们看到了关键词“回文字串”,所以我们先考虑如果对于一个普通的字符串如何求最大回文字串:
我们定义cal(i,j)为从i到j的最大回文子串:
如果 i == j ,cal( i , j ) = 1
如果 i+1 == j:

  • 如果 s[i] == s[j], cal( i , j ) = 2;
  • 如果 s[i] != s[j], cal( i , j ) = 1;

如果有s[i] == s[j] ,cal(i,j) = cal(i+1,j-1)+2;
最后一种情况 cal( i , j ) = max( cal( i , j-1 ),cal( i+1 , j) );

int cal2(int u,int v){
	if(u == v) return 1;
	if(u+1 == v){
		if(a[u] == a[v]) return 2;
		return 1;
	}
	if(f[u][v] != -1) return f[u][v];
	int res = 0;
	
	res = max(cal(u+1,v),cal(u,v-1));
	if(a[u] == a[v]){
		res = max(res,cal(u+1,v-1)+2);
	}
	return f[u][v] = res;
}

而在树上对于两个节点u,v,他们的前一个,后一个节点实际上也是确定的,所以只要对每个节点跑一次dfs,求出每个节点的nex,然后套入同样的思路即可

代码实现:

#include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 2e3 + 10, inf = 0x3f3f3f3f;
vector<int> e[N];
char a[N];
int f[N][N];
int nex[N][N];
void dfs(int u,int fa,int to){
	nex[u][to] = fa;
	for(auto v:e[u]){
		if(v == fa) continue;
		dfs(v,u,to);
	}
}
int cal(int u,int v){
	if(u == v) return 1;
	if(nex[u][v] == v){
		if(a[u] == a[v]) return 2;
		return 1;
	}
	if(f[u][v] != -1) return f[u][v];
	int res = 0;
	
	res = max(cal(nex[u][v],v),cal(u,nex[v][u]));
	if(a[u] == a[v]){
		res = max(res,cal(nex[u][v],nex[v][u])+2);
	}
	return f[u][v] = res;
}

void solve() {
	int n;
	cin >> n;
	string s;
	cin>>s;
	for (int i = 1; i <= n; ++i) {
		e[i].clear();
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			f[i][j] = -1;
			nex[i][j] = 0;
		}
	}
	for (int i = 1; i <= n; ++i) a[i] = s[i - 1];
	for (int i = 1; i < n; ++i) {
		int a, b;
		cin >> a >> b;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	for(int i = 1;i <= n;++i) dfs(i,0,i);
	int maxn = 0;
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= n;++j){
			maxn = max(maxn,cal(i,j));
		}
	}
	cout<<maxn<<endl;


}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;
	cin >> tt;
	while (tt--) solve();


	return 0;
}

ps:本文章仅作为本人的学习笔记,便于复习,思路参考与严格鸽Codeforces Round #837 (Div. 2) C(因数分解) D(树上DP)%%%

标签:return,837,int,res,文字串,Codeforces,nex,cal
From: https://www.cnblogs.com/empty-y/p/16975826.html

相关文章

  • Codeforces Round #837 (Div. 2)补题
    CodeforcesRound#837(Div.2)A.HossamandCombinatorics知识点:简单题复杂度:\(O(nlogn)\)很明显能看出,该题与数据的位置无关,只与大小有关所以我们可直接排序,判断......
  • 题解 CodeForces 940E Cashback
    1.题面描述题目链接给定长为\(n\)的序列和一个整数\(c\),你需要将其分为若干段。对于每一段,若其长度为\(k\),则可以删除其中前\(\lfloor\frac{k}{c}\rfloor\)小的......
  • Codeforces Round #821 (Div. 2)
    比赛链接A题意:给定一个长度为n的数组,你可以任意交换两个距离为k的数,求最大的连续k个数组之和。核心思路:这个我们直接暴力就好了,我们可以把那些距离为k的比较大的全都换......
  • P8377 [PFOI Round1] 暴龙的火锅 题解
    题目传送门题目背景暴龙爱吃火锅。题目描述定义\(S(x)\)表示\(x\)的每一位的数字之和,例如:\(S(14)=1+4=5\),\(S(114514)=1+1+4+5+1+4=16.\)另外,定义\(fib(x)\)代......
  • Educational Codeforces Round 134 (Rated for Div. 2)
    比赛链接A题意:给定4个字符串,每次可以将一种字符串变成另一个字符串,请求最少的操作使得所有字符串相同。核心思路:就是一个找规律的题目,哈哈哈,看多了jly的代码还是有好处......
  • Codeforces Beta Round #2 C. Commentator problem
    题意二维平面上,给定三个圆的原点和半径,求一个点到三个圆的视角相同。三个圆心不共线。思路用(距离/半径)表示视角大小,用方差表示视角的波动。用爬山算法从重心开始四......
  • Codeforces Round #836 (Div. 2)(持续更新)
    Preface补题,上周末没比赛很难受啊,而且这周要考CET-4,这周的模考听力只错了2pts,感觉自信慢慢flag嘛值得一提的是学校还是沦陷了,让我们自愿返乡了但是我知道以我的自制力现......
  • Codeforces 1 C. Ancient Berland Circus
    题意:二维平面中,给定三个点,这三个点是正多边形的三个顶点,求正多边形最小的面积。思路:两对点分别求中垂线,相交点是多边形外接圆的圆心,圆心有了半径和角度也就有了,之后求一......
  • Codeforces 1 B. Spreadsheets
    题意:EXCEL单元格位置表示方法相互转化 R23C55<=>RC23思路AAA<=>26^2+26+1用到知识点:正则表达式匹配字符串反转字符串出现位置C#10.net6代码usin......
  • Codeforces Global Round 1~3
    CF1110C回答\(q\)个关于\(a\)的询问,每次询问求:\(f(a)=max_{0<b<a}gcd(a\bigoplusb,a\&b)\),\(a<2^{25}\)假设\(a\)有\(k\)位,对\(a\)取个反,即\(b=\overlinea\)就......