HDU 5371 Manacher Hotaru's problem

求出一个连续子序列,这个子序列由三部分ABC构成,其中AB是回文串,A和C相同,也就是BC也是回文串。

求这样一个最长的子序列。

Manacher算法是在所有两个相邻数字之间插入一个特殊的数字,比如-1,

Manacher算法跑完之后,就计算出每个数字为中心的回文子序列的最大长度

由题意可以知道,AB和BC必然是长度为偶数的回文串。所以我们枚举回文串的中心就枚举相邻两个数字之间的缝隙,也就是那些-1

把AB中间的间隙叫做左中心i,BC之间的间隙叫做右中心j,那么如果两个中心的范围能够互相覆盖,那么就找到一个符合条件的连续子序列。

做法就是枚举左中心i,在左中心的范围内枚举右中心j,然后维护一个最大值即可。

在枚举j的时候不要直接从[i+1, i + p[i] - 1]枚举,会超时的。

比如说我们维护的最大值是ans,那么直接从 i + ans 开始枚举,因为之前的区间即使找到合法子序列也并不能更新这个最大值。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 100000 + 10;
 8 
 9 int n, tot;
10 int a[maxn], b[maxn * 2];
11 
12 int p[maxn * 2];
13 
14 void Manacher()
15 {
16     int id, mx = 0;
17     p[0] = 0;
18     for(int i = 1; i < tot; i++)
19     {
20         if(mx > i) p[i] = min(p[id * 2 - i], mx - i);
21         else p[i] = 1;
22         while(b[i + p[i]] == b[i - p[i]]) p[i]++;
23         if(i + p[i] > mx) { mx = i + p[i]; id = i; }
24     }
25 }
26 
27 int main()
28 {
29     int T; scanf("%d", &T);
30     for(int kase = 1; kase <= T; kase++)
31     {
32         scanf("%d", &n);
33         for(int i = 0; i < n; i++) scanf("%d", a + i);
34 
35         b[0] = -2, b[1] = -1;
36         tot = 2;
37         for(int i = 0; i < n; i++)
38         {
39             b[tot++] = a[i];
40             b[tot++] = -1;
41         }
42 
43         Manacher();
44 
45         int ans = 1;
46         for(int i = 3; i < tot; i += 2)
47         {
48             for(int j = ans; j <= p[i]; j += 2)
49                 if(p[i + j - 1] >= j) ans = j;
50         }
51 
52         ans = ans / 2 * 3;
53         printf("Case #%d: %d\n", kase, ans);
54     }
55 
56     return 0;
57 }
代码君

 

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4732720.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值