题意是给你一个串 只包含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