码迷,mamicode.com
首页 > 其他好文 > 详细

hdu3613Best Reward

时间:2017-03-25 00:06:01      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:show   ios   代码   strlen   eof   后缀   mem   void   using   

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

方法较多,扩展KMP还不会-_-||

先放上代码,以后再看。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=500050;
 6 int v[28];
 7 int len;
 8 int sum[maxn];
 9 int nex[maxn],ext1[maxn],ext2[maxn];
10 char s[maxn],t[maxn];
11 void KMP_(char *s,char *t,int *ext)
12 {
13     int j=0,k=1;
14     nex[0]=len;
15     while(j+1<len&&t[j]==t[j+1]) j++;
16     nex[1]=j;
17    for(int i=2;i<len;i++)
18    {
19        int n=k+nex[k]-1,l=nex[i-k];
20        if(l<n-i+1) nex[i]=l;
21        else {
22         j=max(0,len-i+1);
23         while(i+j<len&&t[i+j]==t[j]) j++;
24         nex[i]=j;
25         k=i;
26        }
27    }
28    j=0;
29     while(j<len&&s[j]==t[j]) j++;
30     ext[0]=j;
31     k=1;
32     for(int i=1;i<len;i++)
33     {
34         int n=k+ext[k]-1,l=nex[i-k];
35         if(l<n-i+1) ext[i]=l;
36         else {
37             j=max(0,n-i+1);
38             while(i+j<len&&s[i+j]==t[j]) j++;
39             ext[i]=j;
40             k=i;
41         }
42     }
43 
44 }
45 int main()
46 {
47     int r;
48     scanf("%d",&r);
49     while(r--)
50     {
51         memset(sum,0,sizeof(sum));
52         for(int i=0;i<26;i++){
53             scanf("%d",&v[i]);
54         }
55         scanf("%s",s);
56         len=strlen(s);
57         sum[0]=v[s[0]-a];
58         t[len-1]=s[0];
59         for(int i=1;i<len;i++){
60             sum[i]=sum[i-1]+v[s[i]-a];
61             t[len-i-1]=s[i];
62         }
63         t[len]=\0;
64         KMP_(t,s,ext1);
65         KMP_(s,t,ext2);
66         int maxx=-1e-8;
67         for(int i=1;i<len;i++)
68         {
69             int sc=0;
70             if(ext1[len-i]+len-i==len) sc+=sum[i-1];
71             if(ext2[i]+i==len) sc+=sum[len-1]-sum[i-1];
72             maxx=max(maxx,sc);
73         }
74         printf("%d\n",maxx);
75     }
76     return 0;
77 
78 }

 

也可以用manacher解决,相对好理解很多,忘记在哪看的了。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #define INF 99999999
11 using namespace std;
12 
13 const int MAX=500000+10;
14 char s[MAX*2];
15 int p[MAX*2],sum[MAX],val[27];//sum为前i个字符价值和
16 int per[MAX],pos[MAX];//per标记前i个字符为回文串,pos标记后i个字符为回文串
17 
18 int main(){
19     int n;
20     cin>>n;
21     while(n--){
22         for(int i=0;i<26;++i)scanf("%d",&val[i]);
23         scanf("%s",s);
24         int len=strlen(s),id=0,ans=-INF,temp=0;
25         for(int i=1;i<=len;++i)sum[i]=sum[i-1]+val[s[i-1]-a];
26         for(int i=len;i>=0;--i){
27             s[i+i+2]=s[i];
28             s[i+i+1]=#;
29         }
30         s[0]=*;
31         for(int i=2;i<len+len+1;++i){
32             if(p[id]+id>i)p[i]=min(p[2*id-i],p[id]+id-i);
33             else p[i]=1;
34             while(s[i-p[i]] == s[i+p[i]])++p[i];
35             if(id+p[id]<i+p[i])id=i;
36             if(i-p[i] == 0)per[p[i]-1]=n+1;//表示前缀(前p[i]-1个字符)是回文串
37             if(i+p[i] == len+len+2)pos[p[i]-1]=n+1;//表示后缀(后p[i]-1个字符)是回文串
38         }
39         for(int i=1;i<len;++i){
40             if(per[i] == n+1)temp+=sum[i];
41             if(pos[len-i] == n+1)temp+=sum[len]-sum[i];
42             if(temp>ans)ans=temp;
43             temp=0;
44         }
45         cout<<ans<<endl;
46     }
47     return 0;
48 }

 

hdu3613Best Reward

标签:show   ios   代码   strlen   eof   后缀   mem   void   using   

原文地址:http://www.cnblogs.com/yijiull/p/6614000.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!