题意:给你每个字符的价值,再给你一个字符串,要你把这个字符串分成两段,并使得被分开的两段价值和最大.一个串如果是回文,那么它的价值就是所有字符的价值和,否则价值为0。
解法1(exKMP):s串为原串,我们让t串等于s串的reverse。因为回文串有个性质就是reverse前后样子不变,所以我们可以根据这个性质来对每个位置i同时用2次exkmp(对象相反),把当前位置i的前和后是否有回文串找出,并用前缀和来求其价值,每次操作更新当前i的最大价值。
#include<bits/stdc++.h> #pragma GCC optimize(2) #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl ' ' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const int mod=1e9+7; const int maxn=5e5+5; int extend1[maxn],extend2[maxn],net[maxn]; char s[maxn],t[maxn]; void getnext(char *t){ memset(net,0,sizeof(net)); int len=strlen(t); net[0]=len; int a=1,p; while(a<len&&t[a]==t[a-1]) a++; net[1]=a-1; a=1; for(int i=2;i<len;i++){ p=a+net[a]-1; if((i-1)+net[i-a]<p) net[i]=net[i-a]; else{ int j=(p-i+1)>0 ? (p-i+1):0; while(i+j<len&&t[i+j]==t[j]) j++; net[i]=j; a=i; } } } void exkmp(char *s,char *t,int *extend){ getnext(t); int a,p; int lens=strlen(s); int lent=strlen(t); a=p=0; int len=min(strlen(s),strlen(t)); while(p<len&&t[p]==s[p]) p++; extend[0]=p; for(int i=1;i<lens;i++){ p=a+extend[a]-1; if((i-1)+net[i-a]<p) extend[i]=net[i-a]; else{ int j=(p-i+1)>0 ? (p-i+1):0; while(j<lent&&i+j<lens&&s[i+j]==t[j]) j++; extend[i]=j; a=i; } } } int w[maxn],sum[maxn]; int main(){ int T;cin>>T; while(T--){ map<char,int>mp; rep(i,0,25){ int x;cin>>x; mp['a'+i]=x; } scanf("%s",s); int n=strlen(s); for(int i=0;i<n;i++){ t[n-i-1]=s[i]; if(i==0) sum[i]=mp[s[i]]; else sum[i]=sum[i-1]+mp[s[i]]; } exkmp(t,s,extend1); exkmp(s,t,extend2); int ans=-INF; for(int i=1;i<n;i++){ int sc=0; if(extend1[n-i]+n-i==n){ sc+=sum[i-1]; } if(extend2[i]+i==n){ sc+=sum[n-1]-sum[i-1]; } ans=max(ans,sc); } cout<<ans<<endl; } }
解法2(Manacher算法):就是遍历每个#位置(从第2个#到导数第2个#)作为端点的左右最大回文串,判断左右回文串长度是否等于到边界的长度,如果是的话,就利用前缀和进行对当前轮sc加,不断更新最后取最大max(马拉车记得数组开2倍哦)
#include<bits/stdc++.h> #pragma GCC optimize(2) #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl ' ' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const int mod=1e9+7; const int maxn=5e5+5; char s[maxn]; char str[maxn<<1]; int p[maxn<<1],len; int init(){ int len=strlen(s); str[0]='@',str[1]='#'; int j=2; for(int i=0;i<len;i++) str[j++]=s[i],str[j++]='#'; str[j]='