hdu3613 扩展KMP
一个串切成两个,左边如果是回文串加上左边价值,右边如果是回文串加上右边价值,求切一次得到的最大价值
扩展KMP:
for (i=1;i<len;i++)//表示从i开始为一串,i前面为一串
S2为文本串,S1为模式串,extend[len-i]==i,前面1-(i-1)回文
S1为回文串,S2为模式串,extend[i]==len-i,后面i-(len-i)回文
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 int next[500005]; 6 void EKMP(char *s,char *t,int lens,int lent,int *extend) 7 { 8 int i,j,p,l,a; 9 next[0]=lent; j=0; 10 while (j+1<lent&&t[j]==t[j+1]) j++; 11 next[1]=j; 12 a=1; 13 for (i=2;i<lent;i++) 14 { 15 p=next[a]+a-1; 16 l=next[i-a]; 17 if (i+l<p+1) next[i]=l; 18 else{ 19 j=max(0,p-i+1); 20 while (i+j<lent&&t[i+j]==t[j]) j++; 21 next[i]=j; 22 a=i; 23 } 24 } 25 26 j=0; 27 while (j<lens&&j<lent&&s[j]==t[j]) j++; 28 extend[0]=j; a=0; 29 for (i=1;i<lens;i++) 30 { 31 p=extend[a]+a-1; 32 l=next[i-a]; 33 if (l+i<p+1) extend[i]=l; 34 else{ 35 j=max(0,p-i+1); 36 while (i+j<lens&&j<lent&&s[i+j]==t[j]) j++; 37 extend[i]=j; 38 a=i; 39 } 40 } 41 } 42 int v[27],sum[500005],extend2[500005],extend1[500005]; 43 char s[500005],t[500005]; 44 int main() 45 { 46 int T,i,len,maxx,tmp; 47 scanf("%d",&T); 48 while (T--) 49 { 50 for (i=1;i<=26;i++) scanf("%d",&v[i]); 51 scanf("%s",s); 52 len=strlen(s); 53 for (i=0;i<len;i++) 54 { 55 if (i==0) sum[i]=v[s[i]-'a'+1]; 56 else sum[i]=sum[i-1]+v[s[i]-'a'+1]; 57 t[i]=s[len-i-1]; 58 } 59 EKMP(t,s,len,len,extend2); 60 EKMP(s,t,len,len,extend1); 61 maxx=0; 62 for (i=1;i<len;i++) 63 { 64 tmp=0; 65 if (extend2[len-i]==i) tmp+=sum[i-1]; 66 if (extend1[i]==len-i) tmp+=sum[len-1]-sum[i-1]; 67 maxx=max(maxx,tmp); 68 // printf("%d %d\n",i,tmp); 69 } 70 printf("%d\n",maxx); 71 } 72 return 0; 73 }