求助 manacher + 中序遍历 + 建空点
查看原帖
求助 manacher + 中序遍历 + 建空点
222578
jingkongwanglimiaoa楼主2021/8/26 13:55

rt,jr的思路是 为了正常使用manacher的最长回文半径数组,把空的结点存起来,防止因为位置原因出错,但一直只有64pts,后面的点全部挂了,并与答案差的非常非常远(答案个位数,我的输出五位数)数组空间开够了,一直找不到bug

代码有比较详细的注释,求调/给出hack数据/指出问题所在

# include <cstdio>
# include <cstring>
# define N 1e5+5
using namespace std;
int n,l[1000010 * 5],r[1000010 * 5],ize[1000010 * 2],a[1000010 * 5],c[1000010 * 2],an,id,xr,hp,rel[1000010 * 2]; //因为存空点 存树上的点的都开了两倍 又因为manacher 和 manacher有关的又再存了两倍 
//有些数组反复使用 
//后面的真长指的是不含空点的,用来当作答案
//后面的假长是含空点的,用来判定是否符合要求 
void dfs(int p)
{
	if (!p || (!l[p] && !r[p])) // 如果我为空或我是叶结点 
	{
		ize[p] = 1; //假长都为1 
		if (p) rel[p] = 1; //真长只记真点 
		c[++hp] = p;//p进队 
		return ;
	}
	dfs(l[p]);//找左边 
	c[++hp] = p;//记录根节点 
	dfs(r[p]);//找右边 
	ize[p] = 1;
	rel[p] = 1;
	ize[p] = ize[p] + ize[l[p]] + ize[r[p]]; //更新我的假长 
	rel[p] = rel[p] + rel[l[p]] + rel[r[p]]; //更新我的真长 
}
int main()
{
	freopen("1.in","r",stdin);
	scanf("%d",&n);
	for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
	for (int i = 1; i <= n; i++) scanf("%d %d",&l[i],&r[i]),l[i] = l[i] > 0 ? l[i] : 0,r[i] = r[i] > 0 ? r[i] : 0; //把空点预处理为0 
	dfs(1);
	n = 0; //回收 
	r[0] = -2; //manacher传统艺能 
	for (int i = 1; i <= hp; i++) r[++n] = -1,r[++n] = a[c[i]],l[n] = c[i]; //同艺能 此时r数组用来存要处理的串  l数组用来存 在该串第i个位置 对应的是树中哪个节点 
	r[++n] = -1;//补一个井号 
	r[++n] = -3;//防止出错 因为有空点 
	memset(a,0,sizeof(a)); //回收利用a数组  它是回文半径数组  
	for (int i = 1; i <= n; i++)
	{
		// xr是最靠右的回文串 id是它的中点 
		if (a[i] <= xr) a[i] = a[id * 2 - i] < xr - i + 1 ? a[id * 2 - i] : xr - i + 1; 
		while(r[i - a[i]] == r[i + a[i]]) a[i]++; //传统艺能之暴力拓展 
		if (i + a[i] - 1 > xr) id = i,xr = i + a[i] - 1; // 如果这个串更靠右  更新 
		// 回文实际长度为 a[i] - 1 
		if (r[i] > 0 && l[i] > 0 && (a[i] - 1) >= ize[l[i]]) //如果回文长度大过子树长度(含空点) 
		{
			//if (rel[an] < rel[l[i]]) printf("{%d %d %d %d %d %d} \n",an,l[i],rel[l[i]],rel[an],ize[l[i]],a[i]);
			an = rel[an] >= rel[l[i]] ? an : l[i]; //如果比答案更大 
		}
	}
//	for (int i = 0; i <= n; i++) printf("%d ",r[i]);
//	printf("\n");
//	for (int i = 1; i <= n; i++) printf("{%d %d %d %d %d}\n",i,r[i],a[i],ize[l[i]],l[i]);
//	printf("\n");
	printf("%d",rel[an]);
	return 0;
}
2021/8/26 13:55
加载中...