HDU 3613 Best Reward(manacher求前、后缀回文串)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613

题目大意:

题目大意就是将字符串s分成两部分子串,
若子串是回文串则需计算价值,否则价值为0,求分割字符串s能获得的最大价值。

解题思路:

用manacher算法计算出p[i],每次计算p[i]是顺便计算一下这段回文串
是否能到达边界,若能则计算出前缀或者后缀的结束位置,标记起来。//还有之前数组开1e6+5教C++是错的,改成2e6+5就对了,不觉明历。。。。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=2e6+5;
 7 const int INF=0x3f3f3f3f;
 8
 9 int len1,len2;
10 int p[N],sum[N],val[N],pre[N],hou[N];
11 char s[N],str[N];
12
13 void init(){
14     str[0]=‘$‘;
15     str[1]=‘#‘;
16     for(int i=0;i<len1;i++){
17         str[i*2+2]=s[i];
18         str[i*2+3]=‘#‘;
19     }
20     len2=len1*2+2;
21     str[len2]=‘\0‘;
22 }
23
24 void manacher(){
25     int id=0,mx=0;
26     for(int i=1;i<len2;i++){
27         if(mx>i) p[i]=min(p[2*id-i],mx-i);
28         else p[i]=1;
29         while(str[i+p[i]]==str[i-p[i]])
30             p[i]++;
31         if(p[i]+i>mx){
32             id=i;
33             mx=p[i]+i;
34         }
35         if(i-p[i]==0){
36             pre[p[i]+i-1]=1;
37         }
38         if(i+p[i]==len2){
39             hou[i-p[i]+1]=1;
40         }
41     }
42 }
43
44
45 int main(){
46     int t;
47     scanf("%d",&t);
48     while(t--){
49         memset(pre,0,sizeof(pre));
50         memset(hou,0,sizeof(hou));
51         for(int i=0;i<26;i++){
52             scanf("%d",&val[i]);
53         }
54         scanf("%s",s);
55         len1=strlen(s);
56         init();
57         manacher();
58         for(int i=1;i<len2;i++){
59             if(i==‘#‘) sum[i]=sum[i-1];
60             else sum[i]=sum[i-1]+val[str[i]-‘a‘];
61         }
62         int ans=-INF;
63         //枚举分割点
64         for(int i=2;i<len2-1;i++){
65             int tmp=0;
66             if(pre[i]) tmp+=sum[i];
67             if(hou[i]) tmp+=sum[len2-1]-sum[i];
68             ans=max(ans,tmp);
69         }
70         printf("%d\n",ans);
71     }
72     return 0;
73 }

原文地址:https://www.cnblogs.com/fu3638/p/8503573.html

时间: 2024-10-29 19:05:51

HDU 3613 Best Reward(manacher求前、后缀回文串)的相关文章

HDU 3613 Best Reward(求前后缀回文 拓展KMP or Manacher)

题目大意: 给个字符串X,要把X分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串(从左往右或者从右往左读,都一样),那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0.问最多能获得多少价值? 思路: 把字符串X逆序后得到字符串Y 让X去匹配Y ,匹配的长度满足extend[i] + i == len,  len=|X|.    的那么X与y的匹配部分是回文串,这不难理解,画图即可 总复杂度是O(n),由于这是求前缀和后缀的回文,用

HDU 4513 吉哥系列故事——完美队形II manacher求最长回文

题目来源:吉哥系列故事--完美队形II 题意:中文 思路:在manacher算法向两边扩展的时候加判断 保证非严格递减就行了 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100110; int a[maxn<<1]; int b[maxn<<1]; int dp[maxn<<1]; int

Manacher算法 O(n)求最长回文串

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5158    Accepted Submission(s): 1755 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

Manacher求最长回文

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?" 小Ho奇怪的问道:"什么叫做最长回文子串呢?" 小Hi回答道:"一个字符串中连续的一

Manacher(最长镜面回文串)

I - O'My! Gym - 101350I Note: this is a harder version of Mirrored string I. The gorillas have recently discovered that the image on the surface of the water is actually a reflection of themselves. So, the next thing for them to discover is mirrored

HDU 3068-最长回文(Manacher算法O(n)求最长回文串)

题目地址:HDU 3068 关于算法的详解:Manacher算法 #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <set> #include <queue>

Manacher算法 最长回文串

Manacher算法O(n) 因为对于偶回文,是需要从虚轴扩充,ab,ba,所以如下: 先把原字符串处理,都加上一个标记符,比如#(特殊字符任何都可以,对于计算结果不会有影响) 1221-->#1#2#2#1# 121-->#1#2#1# 按照处理后的字符串求它的最长回文串长度m,所以原始字符串最长子回文串的长度是m/2 变量: 1:PArra[] 存放回文半径:某个位置能扩充的回文半径的长度,例如 #1#2#2#1#,2位置PArra[3] = 4 2:int PR 能够扫到的最右的回文的位

Manacher算法—最长回文串

若字符串长度为n,则算法的时间复杂度为o(n) 假设有一个字符串abaaba 先把该字符串变成$  #  a  #  b  #  a  #  a  #  b  #  a  # 第一个字符设为'$',防止计算的时候数组越界 再计算p数组,先给出p数组的答案 i为坐标,ma数组放改变后的字符串,p数组代表以该字符为中心,向右和向左延伸p[i]个,是回文串 i      0  1  2  3  4  5  6  7  8  9  10 11 12 13ma[]   $  #  a  #  b  # 

UVa 11404 回文子序列(LCS求最长回文串长度)

https://vjudge.net/problem/UVA-11404 题意: 给定一个由小写字母组成的字符串,删除其中的0个或多个字符,使得剩下的字母(顺序不变)组成一个尽量长的回文串.如果有多解,输出字典序最小的解. 思路: 首先,最长回文子串的长度可以通过正序字符串和逆序字符串进行LCS得出. 但是这道题目麻烦的是还要输出这个回文串,并且字典序得最小. 应用的主要还是LCS的思想方法,不过在进行状态转移的时候,再加上字符串的状态转移. 不过最后得到的字符串不一定是回文串,但是它的前一半肯