【BZOJ4166】月宫的符卡序列 Manacher+hash

news/2025/3/14 16:39:54/

【BZOJ4166】月宫的符卡序列

题解:题倒不难,就是有点恶心。

首先学习回文串的时候一定学到了这样一个结论:一个长度为n的串的本质不同的回文子串数量不超过n个。

那么我们就可以试图将所有回文串的价值都计算出来,这就需要我们先计算出每个回文中心i的最长回文半径rl[i],那么那些半径在[1,rl[i]]中的,且以i为回文中心的回文串的价值都应该被更新。其实只需要更新最长的那个就行,其余的可以扫一遍回文树,逐层更新上去。但是回文树太大建不出来怎么办?我们可以用hash,直接通过hash值得到每个串在回文树上的父亲。这样就可以更新了。

但是hash要用到map啊,然后本人就被光荣的卡常了。于是采取了一点黑科技~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=2000010;
vector<int> v[maxn];
const ll m1=9997957;
const ll m2=1000000007;
int n,tot,len,ml,pos,mx;
char str[maxn],ss[maxn];
int rl[maxn],ans[maxn],p[maxn];
int head[10000000],next[maxn];
ll h1[maxn],b1[maxn],h2[maxn],b2[maxn],val[maxn];
int find(ll t1,ll t2)
{for(int i=head[t1];i;i=next[i])	if(val[i]==t2)	return i;return 0;
}
void add(ll t1,ll t2)
{val[++tot]=t2,next[tot]=head[t1],head[t1]=tot;
}
void work()
{n=tot=mx=0;memset(ans,0,sizeof(ans));memset(rl,0,sizeof(rl));memset(head,0,sizeof(head));scanf("%s",ss),len=strlen(ss);int i,j,k,t;ll t1,t2;str[n++]='*';for(i=0;i<len;i++)	str[n++]=ss[i],str[n++]='*';for(ml=-1,i=0;i<n;i++){if(i<ml)	rl[i]=min(ml-i+1,rl[2*pos-i]);else	rl[i]=1;for(;rl[i]<=i&&i+rl[i]<n&&str[i+rl[i]]==str[i-rl[i]];rl[i]++);if(i+rl[i]-1>ml)	pos=i,ml=i+rl[i]-1;}for(b1[0]=b2[0]=1,i=1;i<=n;i++)	b1[i]=b1[i-1]*233%m1,b2[i]=b2[i-1]*2333%m2;for(i=0;i<n;i++){if(i)	h1[i]=h1[i-1]*233%m1,h2[i]=h2[i-1]*2333%m2;h1[i]=(h1[i]+str[i])%m1,h2[i]=(h2[i]+str[i])%m2;}for(i=0;i<n;i++){if(rl[i]==1)	continue;t1=(h1[i+rl[i]-1]-h1[i-1]*b1[rl[i]]%m1+m1)%m1;t2=(h2[i+rl[i]-1]-h2[i-1]*b2[rl[i]]%m2+m2)%m2;t=find(t1,t2);if(t){ans[t]^=(i-1>>1);continue;}add(t1,t2),ans[tot]=(i-1>>1),p[tot]=i,v[rl[i]-1].push_back(tot);}for(i=len;i;i--){for(j=0;j<v[i].size();j++){k=v[i][j],mx=max(mx,ans[k]);if(i==1)	continue;t1=(h1[p[k]+i-1]-h1[p[k]-1]*b1[i]%m1+m1)%m1;t2=(h2[p[k]+i-1]-h2[p[k]-1]*b2[i]%m2+m2)%m2;t=find(t1,t2);if(t){ans[t]^=ans[k];continue;}add(t1,t2),ans[tot]=ans[k],p[tot]=p[k],v[i-1].push_back(tot);}v[i].clear();}printf("%d\n",mx);
}
int main()
{int T;scanf("%d",&T);while(T--)	work();return 0;
}

转载于:https://www.cnblogs.com/CQzhangyu/p/7114744.html


http://www.ppmy.cn/news/243414.html

相关文章

洛谷P4166 [SCOI2007]最大土地面积

将四边形拆成两个三角形。旋转卡壳经典题。 #include <bits/stdc.h> using namespace std; typedef long long LL; typedef int lint; const int maxn 2001; const double eps 1e-12; const double PI acos(-1.0); int sgn(double x) {if(fabs(x) < eps)return 0;…

BZOJ 1069 Luogu P4166 最大土地面积 (凸包)

题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id1069 (luogu)https://www.luogu.org/problemnew/show/P4166 题解: 水题&#xff0c;凸包极角排序之后枚举凸四边形对角线\(i,j\)然后找面积最大的点\(k\)&#xff0c;\(k\)随着\(i,j\)是单调的 但是有个易错…

Android中的Intent(显示隐式)

Android中的Intent(显示&隐式) 显示Intent 显示Intent是明确目标Activity的类名 通过Intent(Context packageContext, Class<?> cls)构造方法Intent intent new Intent(this, SecondActivity.class) startActivity(intent);通过Intent的setComponent()方法Componen…

NLP的idea,看了就能水一篇论文

1.问题 在中文情感分析任务中,已有方法仅从单极、单尺度来考虑情感特征&#xff0c;无法充分挖掘和利用情感特征信息&#xff0c;模型性能不理想。 单级单尺度&#xff1a;只从一个方面学习文本的特征 多级多尺度&#xff1a;应该是分别从不同方面学习文本的特征&#xff0c…

一键提升分辨率,呈现更清晰、更细腻的视觉盛宴

牛学长视频修复工具是一款使用AI技术对你的视频分辨率就行调整放大清晰的软件&#xff0c;最高支持8K超高清。 现如今&#xff0c;视频成为人们记录生活、表达创意的重要方式之一。然而&#xff0c;我们常常遇到一个问题&#xff1a;旧有的视频素材分辨率低&#xff0c;画质模…

priority_queue的模拟实现和仿函数

priority_queue模拟 首先查看源代码&#xff0c;源代码就在queue剩下的部分中 push_heap是STL库中的堆算法&#xff0c;STL库中包装有支持堆的算法&#xff0c;在algorithm.h中&#xff1a; 只要不断用堆的形式插入数据&#xff0c;就会形成堆。 priority_queue模拟——初版 pr…

网络协议——STP协议是什么?是如何实现的?

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、STP协议是什么 二、为什么需要STP协议 三、STP的实现过程 ​编辑 1、选举跟桥 2、给非跟桥交换机选举跟端口 3、给每个网段选…

正在解析主机 mirrors.aliyun.com (mirrors.aliyun.com)失败:未知的名称或服务。wget无法解析主机地址

网络问题&#xff1a;做个记录 我这边是更改了链接方式没有问题了就因为之前安装时使用的是nat方式 后来未关机的情况下改成了桥连接出现的问题。ping不通www.baidu.com