hdu3613 扩展KMP

一个串切成两个,左边如果是回文串加上左边价值,右边如果是回文串加上右边价值,求切一次得到的最大价值

扩展KMP:

for (i=1;i<len;i++)//表示从i开始为一串,i前面为一串

S2为文本串,S1为模式串,extend[len-i]==i,前面1-(i-1)回文

S1为回文串,S2为模式串,extend[i]==len-i,后面i-(len-i)回文

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int next[500005];
 6 void EKMP(char *s,char *t,int lens,int lent,int *extend)
 7 {
 8   int i,j,p,l,a;
 9   next[0]=lent; j=0;
10   while (j+1<lent&&t[j]==t[j+1]) j++;
11   next[1]=j;
12   a=1;
13   for (i=2;i<lent;i++)
14   {
15     p=next[a]+a-1;
16     l=next[i-a];
17     if (i+l<p+1) next[i]=l;
18     else{
19       j=max(0,p-i+1);
20       while (i+j<lent&&t[i+j]==t[j]) j++;
21       next[i]=j;
22       a=i;
23     }
24   }
25 
26   j=0;
27   while (j<lens&&j<lent&&s[j]==t[j]) j++;
28   extend[0]=j; a=0;
29   for (i=1;i<lens;i++)
30   {
31     p=extend[a]+a-1;
32     l=next[i-a];
33     if (l+i<p+1) extend[i]=l;
34     else{
35       j=max(0,p-i+1);
36       while (i+j<lens&&j<lent&&s[i+j]==t[j]) j++;
37       extend[i]=j;
38       a=i;
39     }
40   }
41 }
42 int v[27],sum[500005],extend2[500005],extend1[500005];
43 char s[500005],t[500005];
44 int main()
45 {
46   int T,i,len,maxx,tmp;
47   scanf("%d",&T);
48   while (T--)
49   {
50     for (i=1;i<=26;i++) scanf("%d",&v[i]);
51     scanf("%s",s);
52     len=strlen(s);
53     for (i=0;i<len;i++)
54     {
55       if (i==0) sum[i]=v[s[i]-'a'+1];
56       else sum[i]=sum[i-1]+v[s[i]-'a'+1];
57       t[i]=s[len-i-1];
58     }
59     EKMP(t,s,len,len,extend2);
60     EKMP(s,t,len,len,extend1);
61     maxx=0;
62     for (i=1;i<len;i++)
63     {
64       tmp=0;
65       if (extend2[len-i]==i) tmp+=sum[i-1];
66       if (extend1[i]==len-i) tmp+=sum[len-1]-sum[i-1];
67       maxx=max(maxx,tmp);
68 //      printf("%d %d\n",i,tmp);
69     }
70     printf("%d\n",maxx);
71   }
72   return 0;
73 }
View Code

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

posted on 2015-02-03 23:11  xiao_xin  阅读(99)  评论(0编辑  收藏  举报

导航