1. 程式人生 > 實用技巧 >Best Reward HDU - 3613 字串切一刀迴文最大價值

Best Reward HDU - 3613 字串切一刀迴文最大價值

題目連結

題意:給你一個字串問切一刀的最大價值。會給出26個字母的價值,而如果你切出來的一個字串是迴文串,則價值為迴文串所有字母的和,否則為0.求最大價值。值得注意的是,字母價值可能為負數。

思路:可以想到馬拉車演算法求出P陣列,然後暴力列舉。先預處理出字母價值的字首和然後再去暴力。暴力過程中還是有很多細節,比如你前和後兩個字串都是迴文如何判斷,前是迴文,後不是迴文,前不是迴文,後是迴文,前後都不是迴文。四種情況都要想好確切思路去判斷。我是先遍歷,找出哪個字尾是迴文,然後在去暴力列舉,注意之後操作都在text串中而不是原串。分類討論一切都在程式碼中。

#include <iostream>
#include 
<string> #include <cstring> #include <algorithm> #include <cstdio> #include <cctype> #include <queue> #include <stdlib.h> #include <cstdlib> #include <math.h> #include <set> #include"queue" #include <vector> #define inf 107374182 #define
M 10010001 #define ll long long #define PII pair<int,int> using namespace std; const int maxn=2000110; char a[maxn],text[maxn]; int P[maxn]; int b[100]; int c[maxn]; int sum[maxn]; void pre_treat(){ int len = strlen(a); for(int i=0;i<len;i++){ text[i*2] = '#'; text[i*2+1] = a[i]; } text[len
*2]='#';text[len*2+1]='\0'; } void manacher(){ P[0] = 1; //第一個字元的迴文串肯定是1 int len = strlen(text); int md = 0; for(int i=1;i<len;i++){ if(i<md+P[md]){ int k = P[md*2-i]; //找到對稱點的迴文串長度 if(i+k<md+P[md]) P[i] = k; //迴文串沒有超過右界 else{ k = md+P[md]-i; while(i+k<len&&i+k>=0&&text[i+k]==text[i-k]) k++; md = i; P[i] = k; } } else{ int k = 1; while(i+k<len&&i+k>=0&&text[i+k]==text[i-k]) k++; md = i; P[i] = k; } } // for(int i=0;i<len;i++) printf("%d ",P[i]); //(處理之後的每個點的迴文串的長度)/2+1 // printf("\n"); } int main() { int t; scanf("%d",&t); while(t--) { for(int i=0;i<26;i++) { scanf("%d",&b[i]); } scanf("%s",a); pre_treat(); int n=strlen(text); for(int i=0;i<=n+1;i++) P[i]=0,c[i]=0; manacher(); sum[0]=0; for(int i=1;i<n;i++) { if(text[i]>='a'&&text[i]<='z') { sum[i]=sum[i-1]+b[text[i]-'a']; } else { sum[i]=sum[i-1]; } } for(int i=n-1;i>=0;i--) { if(i+P[i]-1==n-1) { c[i-P[i]+1]=1; } } int ans=-1000000000; for(int i=1;i<n;i++) { if(c[i]==1) { ans=max(ans,sum[n-1]-sum[i-1]);//前一個不是迴文,後面是迴文 } if(i-P[i]+1==0&&i+P[i]-1!=n-1) { if(c[i+P[i]-1]==1) { ans=max(ans,sum[n-1]);//都是迴文 c[i+P[i]-1]=2; } else { ans=max(ans,sum[i+P[i]-1]);//前一個是迴文,後一個不是 } } else { ans=max(0,ans);//都不是迴文 } } printf("%d\n",ans); } }