hdu 3613 扩展kmp+回文串

题目大意:
给个字符串S,要把S分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串(从左往右或者从右往左读,都一样),那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0。问最多能获得多少价值?

 

对于我们只需要枚举扫描一遍extend数组,扫描到的当前位置之前为前半部分T1,
然后用根据extend数组可以判断T1是否是回文。那后半部分T2呢?  刚才是用S去匹配T,
如果要求后缀,只需要用T去匹配S,再得到一个数组extend2即可,根据这个extend2判断后半部分T2是否是回文。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 using namespace std;
  9 #define MOD 1000000007
 10 const int INF=0x3f3f3f3f;
 11 const double eps=1e-5;
 12 #define cl(a) memset(a,0,sizeof(a))
 13 #define ts printf("*****\n");
 14 const int MAXN=500005;
 15 int n,m,tt;
 16 char s1[MAXN],s2[MAXN];
 17 int v[29],sum[MAXN];
 18 void pre_EKMP(char x[],int m,int nextt[])
 19 {
 20     nextt[0]=m;
 21     int j=0;
 22     while(j+1<m && x[j]==x[j+1])j++;
 23     nextt[1]=j;
 24     int k=1;
 25     for(int i=2;i<m;i++)
 26     {
 27         int p=nextt[k]+k-1;
 28         int L=nextt[i-k];
 29         if(i+L<p+1)nextt[i]=L;
 30         else
 31         {
 32             j=max(0,p-i+1);
 33             while(i+j<m && x[i+j]==x[j])j++;
 34             nextt[i]=j;
 35             k=i;
 36         }
 37     }
 38 }
 39 void EKMP(char x[],int m,char y[],int n,int nextt[],int extend[])
 40 {
 41     pre_EKMP(x,m,nextt);
 42     int j=0;
 43     while(j<n && j<m && x[j]==y[j])j++;
 44     extend[0]=j;
 45     int k=0;
 46     for(int i=1;i<n;i++)
 47     {
 48         int p=extend[k]+k-1;
 49         int L=nextt[i-k];
 50         if(i+L<p+1)extend[i]=L;
 51         else
 52         {
 53             j=max(0,p-i+1);
 54             while(i+j<n && j<m && y[i+j]==x[j])j++;
 55             extend[i]=j;
 56             k=i;
 57         }
 58     }
 59 }
 60 int nextt[MAXN],extend1[MAXN],extend2[MAXN];
 61 int main()
 62 {
 63     int i,j,k;
 64     #ifndef ONLINE_JUDGE
 65     freopen("1.in","r",stdin);
 66     #endif
 67     scanf("%d",&tt);
 68     while(tt--)
 69     {
 70         for(i=0;i<26;i++)
 71         {
 72             scanf("%d",&v[i]);
 73         }
 74         scanf("%s",s1);
 75         int len=strlen(s1);
 76         for(i=0;i<len;i++)
 77         {
 78             sum[i+1]=v[s1[i]-‘a‘]+sum[i];
 79         }
 80         strcpy(s2,s1);
 81         strrev(s2);
 82         EKMP(s2,len,s1,len,nextt,extend1);
 83         EKMP(s1,len,s2,len,nextt,extend2);
 84         int maxx=0;
 85         for(i=1;i<len;i++)  //枚举断点
 86         {
 87             int tot=0;
 88             if(i+extend1[i]==len)   //这里求的是断点后面的
 89             {
 90                 tot+=sum[len]-sum[i];
 91             }
 92             int ll=len-i;
 93             if(ll+extend2[ll]==len)
 94             {
 95                 tot+=sum[len]-sum[ll];
 96             }
 97             maxx=max(maxx,tot);
 98         }
 99         printf("%d\n",maxx);
100     }
101 }
时间: 2024-12-16 11:59:19

hdu 3613 扩展kmp+回文串的相关文章

HDU 3068 &amp;&amp;HDU 3294 +最长回文串*3—— manacher/扩展KMP/DP

HDU 3068 http://acm.hdu.edu.cn/showproblem.php?pid=3068 HDU 3294http://acm.hdu.edu.cn/showproblem.php?pid=3294 扩展KMP:https://segmentfault.com/a/1190000008663857 感觉DP相对实现起来更简洁一些,很容易想到,可以用bool dp[i][j]:表示从i到j是否为回文串,然后最长长度用一个变量记录就好 如果dp[i][j]为回文串,那么dp[i

HDOJ/HDU 2163 Palindromes(判断回文串~)

Problem Description Write a program to determine whether a word is a palindrome. A palindrome is a sequence of characters that is identical to the string when the characters are placed in reverse order. For example, the following strings are palindro

hdu 3068 最长回文串 o(n) Manacher 算法

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

HDU 1513 Palindrome 求回文串

这个题是走弯路了,刚开始自己DP出了方程,无限MLE,唉 if(s1[i]==s1[j]) dp[i][j]=dp[i+1][j-1]; else dp[i][j]=min(dp[i][j-1],dp[i+1][j]) +1; 后来百度了一下,这个原来是个经典回文串问题,即先将串置反,然后求LCS........ 然后就是这题卡时间卡的特别厉害,多用了一次strlen就TLE AC: #include<cstdio> #include<string> #include<str

hdu 3294 manacher 求回文串

感谢: http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ O(n)求给定字符串的以每个位置为中心的回文串长度. 中心思想:每次计算位置i的答案时,利用已经算出的1~i-1位置的答案. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define maxn 222222 5 using namespace std; 6 7

hdu 3613 扩展KMP运用

题意是给你一个串    只包含a-z   每个字母对应一个价值    问把他进行一次分割成两段     若其中一段是会问串  子价值为之和否则为零     问最大的价值: 先把串str1进行反转 为str2       判断s1的前i个是不是回文串   对str2(文本串)  str1(模式串)进行EKMP   只要i==extand1[len-i] 则是回文   若要判断后i个是不是回文串 则反过来把str1作文本串  str2作模式串   进行EKMP   就ok了 #include<std

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 5371(Hotaru&#39;s problem-2次回文串)

Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2432    Accepted Submission(s): 841 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playin

(最长回文串 模板) 最长回文 -- hdu -- 3068

http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12079    Accepted Submission(s): 4430 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长