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 }

 

转载于:https://www.cnblogs.com/cnblogs321114287/p/4466487.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值