扩展KMP --- HDU 3613 Best Reward

Best Reward

Problem‘s Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3613



Mean:

给你一个字符串,每个字符都有一个权值(可能为负),让你将这个字符串分成两个字串,使得这两个子串的价值之和最大。一个子串价值的计算方法:如果这个子串是回文串,那么价值就是这个子串所有字符权值之和;否则价值为0。

analyse:

经典的扩展KMP算法运用。

假设输入串为s,那么我们首先:strcpy(s1,s)     ;      s_tmp=s.reverse()   ;       s1[s1.length()]=‘#‘       strcat(s1,s_tmp);

根据s1求一遍next,我们就可以得到所有以s[0]开头的子串的回文串长度;

然后:

strcpy(s2,s_tmp)   ;       s2[s2.length()]=‘#‘;           strcat(s2,s);

根据s2求一遍next,我们就可以得到所有以s[len-1]结尾的子串的回文串长度。

最后只需从头到位扫一遍,每次判断前半部分是不是回文和后半部分是不是回文,然后求出最大值即可。

Time complexity: O(nlogn)

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-05-06-22.02
* Time: 0MS
* Memory: 137KB
*/
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#include <cstdlib>
#include <climits>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>
#define  MAXN 500005
#define  LL long long
using namespace std;
char s[MAXN<<1];
int Next[MAXN<<1],value[30];
int sum[MAXN],v[2][MAXN];
int n,m;
void get_Next()
{
    int i=0,j=-1;
    Next[0]=-1;
    for(;i<m;)
        if(j==-1||s[i]==s[j])
        {
            ++i;++j;
            Next[i]=j;
        }
        else j=Next[j];
}
void check(int x)
{
    sum[0]=0;
    for(int i=0;i<n;++i)
        sum[i+1]=sum[i]+value[s[i]-‘a‘];
    reverse_copy(s,s+n,s+n+1);
    s[n]=‘#‘;
    get_Next();
    memset(v[x],0,sizeof(v[x]));
    int p=m;
    for(;;)
    {
        p=Next[p];
        if(!p) break;
        v[x][p]=sum[p];
    }
}
int main()
{
    int cas;
    scanf("%d",&cas);
    for(;cas--;)
    {
        int ans=INT_MIN;
        for(int i=0;i<26;++i) scanf("%d",&value[i]);
        scanf("%s",s);
        n=strlen(s);
        m=2*n+1;
        check(0);
        reverse(s,s+n);
        check(1);
        reverse(v[1],v[1]+n+1);
        for(int i=1;i<n;++i)
            ans=max(ans,v[0][i]+v[1][i]);
        printf("%d\n",ans);
    }
    return 0;
}

时间: 2024-07-30 20:25:11

扩展KMP --- HDU 3613 Best Reward的相关文章

HDU 3613 Best Reward 正反两次扩展KMP

题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考虑扩展KMP 输出a串 得到a的反串b 求出f[0]和f[1] 和 extend[0]和extend[1] 正反求2次 枚举位置i 分成2部分0到i-1 和i到n-1 由于分成的2部分必须组成原字符串 就是不能多也不能少 那么推断i+extend[i]是否等于n 等于说明i到n-1这个部分是回文串

HDU - 3613 Best Reward(manacher或拓展kmp)

传送门:HDU - 3613 题意:给出26个字母的价值,然后给你一个字符串,把它分成两个字符串,字符串是回文串才算价值,求价值最大是多少. 题解:这个题可以用马拉车,也可以用拓展kmp. ①Manacher:先记录下第i个字符的价值,然后求前缀和.然后遍历分的位置,分别判断前半段和后半段是否为回文串,是回文串的加上这段的价值(前缀和相减),更新最大价值. 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int p[1000100],v

扩展KMP - HDU 4333 Revolving Digits

Revolving Digits Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=4333 Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. analyse: KMP的经典题. 首先我们将原串扩展成两倍,算一遍扩展KMP(自匹配),时间复杂度O(n). 这样一来,我们就得到了eKMP[i],eKMP[i]代表s[i...len-1]与s的最长

HDU 3613 Best Reward(扩展KMP)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3613 [题目大意] 一个字符串的价值定义为,当它是一个回文串的时候,价值为每个字符的价值的和,如果不是回文串,价值为0,现在给出每种字符的价值.给出一个字符串,要求将其划分为两个子串,要求两个子串的价值和最大. [题解] 求出字符串S的反串T,以T为模板跑一遍S的exkmp就能得到S的后缀是否为回文串的信息,同理以S为模板跑一遍T就可以得到S的前缀是否是回文串的信息,枚举每个断点,取最大值即可.

HDU 3613 Best Reward(拓展KMP算法求解)

题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his great exploit. One of these treasures is a necklace made up of 26 differe

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 3613 Best Reward

Best Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)http://acm.hdu.edu.cn/showproblem.php?pid=3613 Problem Description After an uphill battle, General Li won a great victory. Now the head of state decide to

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<ios

hdu 3613 Best Reward (manachar算法)

Best Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his gr