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 }

 

你可能感兴趣的:(HDU)