HDU 3613 Best Reward(扩展KMP求前后缀回文串)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 

题目大意:

大意就是将字符串s分成两部分子串,
若子串是回文串则需计算价值,否则价值为0,求分割字符串s能获得的最大价值。

解题思路:将原串s反转得到rs,然后进行rs,s扩展KMP匹配,得到extend,对于s1的前i个字符如果和s2的后i个字符相等即extend[len-i] == i则前i个字符为回文串;

同理,判断后len-i个字符是否是回文串用s,rs进行扩展KMP再生成一个extend即可。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1e6+5;
 7 const int INF=0x3f3f3f3f;
 8 
 9 int nxt[N],extend1[N],extend2[N],val[N],sum[N];
10 char s[N],rs[N];
11 
12 void getnext(char *t){
13     int a,p,len;
14     len=strlen(t);
15     nxt[0]=len;
16     for(int i=1,j=-1;i<len;i++,j--){
17         if(j<0||i+nxt[i-a]>=p){
18             if(j<0)
19                 p=i,j=0;
20             while(p<len&&t[p]==t[j])
21                 p++,j++;
22             nxt[i]=j;
23             a=i;
24         }
25         else
26             nxt[i]=nxt[i-a];
27     }
28 }
29 
30 void ex_kmp(char *s,char *t,int *extend){
31     int a,p,len1,len2;
32     len1=strlen(s);
33     len2=strlen(t);
34     for(int i=0,j=-1;i<len1;i++,j--){
35         if(j<0||i+nxt[i-a]>=p){
36             if(j<0)
37                 p=i,j=0;
38             while(p<len1&&j<len2&&s[p]==t[j])
39                 p++,j++;
40             extend[i]=j;
41             a=i;
42         }
43         else extend[i]=nxt[i-a];
44     }
45 }
46 
47 int main(){
48     int t;
49     scanf("%d",&t);
50     while(t--){
51         for(int i=0;i<26;i++){
52             scanf("%d",&val[i]);
53         }
54         scanf("%s",s);
55         int len=strlen(s);
56         for(int i=0;i<len;i++){
57             rs[len-i-1]=s[i];
58         }
59         getnext(rs);
60         ex_kmp(s,rs,extend1);
61         getnext(s);
62         ex_kmp(rs,s,extend2);
63         for(int i=0;i<len;i++){
64             sum[i]=val[s[i]-'a'];
65             if(i!=0)
66                 sum[i]+=sum[i-1];
67         }
68         int ans=-INF;
69         //枚举分割位置(把s[i]归给前面的子串)
70         for(int i=0;i<len-1;i++){
71             int tmp=0;
72             if(extend2[len-i]==i) tmp+=sum[i];
73             i++;
74             if(extend1[i]==len-i) tmp+=sum[len-1]-sum[i-1];
75             ans=max(ans,tmp);
76         }
77         printf("%d
",ans);
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/fu3638/p/8503577.html