bzoj4166 月宫的符卡序列

news/2025/3/14 5:49:04/

  • 题目大意
  • 输入格式
  • 输出格式
  • 样例
    • 样例输入
    • 样例输出
    • 样例说明
  • 题解
    • 代码很丑

题目大意

给定一个包含26个小写字母的字符串,字符从0开始标号。一个子串a的价值定义为:a在S中的所有出现位置中点的异或值。(规定:若a出现在s[l……r],那么a的中点为 l+r2() ).求:对于所有 回文子串 a,最大的价值是多少?

输入格式

第一行,一个整数num,( 1num5 ),表示数据组数;
每组数据占一行,有一个仅含小写字母的字符串S.

输出格式

对于每组数据,输出一行,表示最大价值.

样例

样例输入

1
aabacabaaa

样例输出

15

样例说明

对于回文子串aa,所有出现位置的中点为:0,7,8;
0^7^8=15

题解

回文自动机记的是右端点,似乎不太好用,关键是我不会写回文树。
所以还是考虑一下manacher+hash.
先用manacher跑一遍字符串,可以看出,只有在暴力扩展右边界时会产生新的本质不同的回文串.
这些本质不同的回文串的数目是O(n)的。
我们需要把中间部分相同的串连接起来形成一棵树.
比如:abbba是bbb的子节点,bbb是b的子节点.子串用hash值映射到节点.
本来用的是map,发现超时很严重,于是看了下网上各位大佬的代码,发现大佬们用的是hash_table.
居然用黑科技!我等蒟蒻还是用链表hash算了。

代码(很丑)

#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#include<map> 
using namespace std; 
#define MAXN 1005000 
#define LL long long 
#define ULL unsigned long long 
const ULL s1=131,s2=129; 
const ULL m1=19980403,m2=998244353; 
char s[MAXN],t[MAXN*2]; 
ULL h1[MAXN],h2[MAXN],pow1[MAXN],pow2[MAXN];
int Next[MAXN<<2],End[MAXN<<2],Last[m1+10],Len[MAXN<<2],e=0;
void add(ULL x,int p)
{ULL a,b;a=x>>32;b=x-(a<<32);End[++e]=b;Len[e]=p;Next[e]=Last[a];Last[a]=e;return ;
}
int find(ULL x)
{ULL a,b;a=x>>32;b=x-(a<<32);for(int t=Last[a];t;t=Next[t]){if(End[t]==b){return Len[t];}}return -1;
}
int L,len; 
map<ULL,int>T; 
void init() 
{ pow1[0]=pow2[0]=1; h1[0]=h2[0]=0; for(int i=1;i<=L;i++) { pow1[i]=pow1[i-1]*s1%m1; pow2[i]=pow2[i-1]*s2%m2; h1[i]=(h1[i-1]*s1+s[i])%m1; h2[i]=(h2[i-1]*s2+s[i])%m2; } return ; 
} 
ULL cal(int l,int r) 
{ ULL t1,t2; t1=(h1[r]+m1-h1[l-1]*pow1[r-l+1]%m1)%m1; t2=(h2[r]+m2-h2[l-1]*pow2[r-l+1]%m2)%m2; return (t1<<32)|t2; 
} 
int fa[MAXN],dp[MAXN],p[MAXN*2],tot=0,ans=0; 
void work() 
{ memset(p,0,sizeof(p));memset(s,0,sizeof(s));memset(Last,0,sizeof(Last));e=0;//T.clear(); tot=0; scanf("%s",s+1); L=strlen(s+1); init(); t[0]='$'; len=0; for(int i=1;i<=L;i++) { t[++len]='#'; t[++len]=s[i]; } t[++len]='#'; t[++len]='@'; int mx=0,id=0,lst; ULL tt;for(int i=1;i<len;i++) { p[i]=mx>i?(min(mx-i,p[(id<<1)-i])):1; //lst=(p[i]==1)?0:T[cal(((i-p[i])>>1)+1,(i+p[i]-1)>>1)];lst=(p[i]==1)?0:find(cal(((i-p[i])>>1)+1,(i+p[i]-1)>>1)); for(;t[i-p[i]]==t[i+p[i]];) { ++p[i]; tt=cal(((i-p[i])>>1)+1,(i+p[i]-1)>>1);if(find(tt)<0) { //T[tt]=++tot;++tot;add(tt,tot); dp[tot]=0;fa[tot]=lst; lst=tot; } else { //lst=T[tt]; lst=find(tt);} } if(lst) { dp[lst]^=(i>>1)-1; } if(i+p[i]>mx) { mx=i+p[i]; id=i; } } ans=0; for(int i=tot;i>=1;i--) { ans=max(ans,dp[i]); dp[fa[i]]^=dp[i]; } printf("%d\n",ans); return ; 
} 
int main() 
{ int Tt; scanf("%d",&Tt); while(Tt) { work(); --Tt; } return 0; 
}

上面这段丑代码,显然是用了map发现T了,然后改成链表的。链表部分的变量名沿用了链式存图的变量名.


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

相关文章

洛谷4166 最大土地面积(计算几何)

有毒。。。。 【题目分析】 首先讲一波错误的想法&#xff08;来自wcr dalao&#xff09; 为什么要去找最远点对呢&#xff1f;反例太好找了啊&#xff01; 好的讲讲正解&#xff0c;首先要找最大面积&#xff0c;肯定要在凸包上去找四个点&#xff08;证明等我思考出来就更传送…

luogu4166 最大土地面积 (旋转卡壳)

首先这样的点一定在凸包上 然后旋转卡壳就可以 具体来说&#xff0c;枚举对角线的一个端点&#xff0c;另一个端点在凸包上转&#xff0c;剩下两个点就是一个叉积最大一个最小&#xff0c;而这两个点也是跟着转的 所以是$O(N^2)$ 1 #include<bits/stdc.h>2 #include<t…

hdu~4166~Robot Navigation

此题用的广搜加记忆化&#xff0c;一开始没考虑方向&#xff0c;测试数据都过不了&#xff0c;在队友的提醒下才发现&#xff0c;改了之后广搜过了&#xff0c;深搜却错了&#xff0c;调了无数个小错误之后&#xff0c;终于过了测试数据&#xff0c;汗啊&#xff01;&#xff0…

bzoj4166 月宫的符卡序列(manacher+链状双hash)

分析&#xff1a; 网上的题解少之又少&#xff0c;而且都是dalao码风&#xff0c;所以只能自力更生了 仔细分析一下&#xff0c;这道题就是求解本质不同的回文串以及出现位置 由于字符串比较长&#xff0c;我们需要用manacher算法 在manacher算法中&#xff0c;只有发生了扩…

【洛谷 P4166】 [SCOI2007]最大土地面积(凸包,旋转卡壳)

题目链接 又调了我两个多小时巨亏 直接\(O(n^4)\)枚举4个点显然不行。 数据范围提示我们需要一个\(O(n^2)\)的算法。 于是\(O(n^2)\)枚举对角线&#xff0c;然后在这两个点两边各找一个点使其和对角线构成的三角形面积最大&#xff0c;也就是叉积的绝对值最大。显然具有单调性&…

HDU 4166 BNU 32715 Robot Navigation (记忆化bfs)

题意&#xff1a;给一个二维地图&#xff0c;每个点为障碍或者空地&#xff0c;有一个机器人有三种操作&#xff1a;1、向前走&#xff1b;2、左转90度&#xff1b;3、右转90度。现给定起点和终点&#xff0c;问到达终点最短路的条数。 思路&#xff1a;一般的题目只是求最短路…

P4166 [SCOI2007]最大土地面积

传送门 首先&#xff0c;四边形的四个点肯定都在凸包上&#xff08;别问我为什么我也不知道&#xff0c;感性理解一下好了&#xff09; 那么我们可以求出凸包之后\(O(n^4)\)暴力枚举&#xff0c;据说在随机数据下凸包上的点只有\(O(logn)\)个可过 然而出题人大大的没有良心&…

HDU 4166 Robot Navigation

题意&#xff1a; 一个机器人走迷宫 每一秒要么转向要么前进 问 最少时间的情况下有几种方案 思路&#xff1a; 记忆化搜索即可 简单bfs 代码&#xff1a; #include<cstdio> #include<iostream> #include<cstring> #include<string> #include&…