hdu 3613 扩展KMP运用

题意是给你一个串    只包含a-z   每个字母对应一个价值    问把他进行一次分割成两段     若其中一段是会问串  子价值为之和否则为零     问最大的价值;

先把串str1进行反转 为str2       判断s1的前i个是不是回文串   对str2(文本串)  str1(模式串)进行EKMP   只要i==extand1【len-i】 则是回文   若要判断后i个是不是回文串

则反过来把str1作文本串  str2作模式串   进行EKMP   就ok了

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

char str1[500010],str2[500010];
int next[500010],extand1[500010],extand2[500010];
int sum[500010];
int get_next(char str[],int len)
{
    memset(next,0,sizeof(next));
    next[0]=len;
    int a=0;
    while(a<len-1&&str[a]==str[a+1]) a++;
    next[1]=a;
    a=1;
    for(int i=2;i<len;i++)
    {
        int p=a+next[a]-1;
        int L=next[i-a];
        if(L+i+1>=p)
        {
            int j=p-i+1>0?p-i+1:0;
            while(i+j<len&&str[i+j]==str[j]) j++;
            next[i]=j;
            a=i;
        }
        else next[i]=L;
    }
    return 0;
}
int EKMP(char str1[],char str2[],int len,int *extand)
{
    get_next(str2,len);
    int a=0;
    while(a<len&&str1[a]==str2[a]) a++;
    extand[0]=a;
    a=1;
    for(int i=1;i<len;i++)
    {
        int p=a+extand[a]-1;
        int L=next[i-a];
        if(L+i-1>=p)
        {
            int j=p-i+1>0?p-i+1:0;
            while(i+j<len&&str1[i+j]==str2[j]) j++;
            extand[i]=j;
            a=i;
        }
        else extand[i]=L;
    }
    return 0;
}
int main()
{
    int T,i,j;
    int num[100];
    scanf("%d",&T);
    while(T--)
    {
        for(i=0;i<26;i++)
        {
            scanf("%d",&num[i]);
        }
        scanf("%s",str1);
        int len=strlen(str1);
        sum[0]=0;
        for(i=0;i<len;i++)
        str2[i]=str1[len-i-1];
        for(i=1;i<=len;i++)
        sum[i]=sum[i-1]+num[str1[i-1]-‘a‘];
        EKMP(str1,str2,len,extand1);
        EKMP(str2,str1,len,extand2);
        int Max=-1,s;
        for(i=1;i<len;i++)
        {
            s=0;
            if(i==extand2[len-i]) s+=sum[i];
            if(len-i==extand1[i]) s+=sum[len]-sum[i];
            if(s>Max) Max=s;
        }
        printf("%d\n",Max);
    }
    return 0;
}
时间: 2024-10-08 08:37:19

hdu 3613 扩展KMP运用的相关文章

hdu 3613 扩展kmp+回文串

题目大意:给个字符串S,要把S分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串(从左往右或者从右往左读,都一样),那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0.问最多能获得多少价值?   对于我们只需要枚举扫描一遍extend数组,扫描到的当前位置之前为前半部分T1, 然后用根据extend数组可以判断T1是否是回文.那后半部分T2呢?  刚才是用S去匹配T, 如果要求后缀,只需要用T去匹配S,再得到一个数组extend2即

hdu 4333 扩展kmp+kmp重复字串去重

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 关于kmp next数组求最短重复字串问题请看:http://www.cnblogs.com/z1141000271/p/7406198.html 扩展kmp请看:http://www.cnblogs.com/z1141000271/p/7404717.html 题目大意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算 题解:

HDU 3336 扩展kmp

题目大意: 找到字符串中所有和前缀字符串相同的子串的个数 对于这种前缀的问题,通常通过扩展kmp来解决 其实吧这是我第一次做扩展kmp的题目,原来确实看过这个概念,今天突然做到,所以这个扩展kmp的模板是做到这道题直接copy的 这里用扩展kmp很好解决问题,_next[i],表示第i位开始所能匹配到的最大公共前缀长度,比如说这个长度为4,那么说明前缀1,2,3,4都出现了一次,我们只在cnt[4]++ 那么最后从n到1,逆向更新cnt[i] += cnt[i+1]即可,最后得到cnt[i]就表

HDU 4333 扩展KMP

点击打开链接 题意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算 思路:用扩展KMP我们可以处理,先将串复制到后面一次,然后求扩展KMP,那么我们如何比较呢,如果extand[i]的值大于串的长度len,说明我以i为开头的串和原串的匹配大于len,也就说明这个串和原串相等,接下来就是另外两种情况,若extand[i]匹配到了第三位,那么久比较原串的第三位和以i开始的第三位即可,比较过后,处理重复的串,用KMP即可处理,如果串是

HDU 2594 扩展kmp模板题

题目大意: 给定两个字符串,在第一个字符串中找到一个最大前缀作为第二个字符串的后缀 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <climits> 8 #include <cmath>

HDU 6153 A Secret(扩展KMP模板题)

A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Total Submission(s): 2523    Accepted Submission(s): 934 Problem Description Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,w

扩展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)     ;      

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这个部分是回文串

扩展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的最长