您的位置:首页 > 其它

hdu 3613 (KMP)回文串

2013-07-28 18:04 309 查看
将模板串s倒置,并尾加到原串后,求得next[]数组,根据next[]数组的性质,便可得前缀的回文串,

同理交原串尾加到倒置串后,便可求得后缀的回文串,然后前缀串和后缀串分开,遍历即可求得最大值!

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 1000010
int v[26], rsum[N/2], lsum[N/2], sum1[N/2], sum2[N/2], next
;
char s[N/2], s1
, s2
;

void getfail(char* s, int len){   //next[]数组
next[0] = 0; next[1] = 0;
for(int i = 1; i < len; ++i){
int j = next[i];
while(j && s[j] != s[i]) j = next[j];
next[i+1] = s[i] == s[j] ? j + 1 : 0;
}
}

int main()
{
int t, i;
scanf("%d",&t);
while(t--){
for(i = 0; i < 26; ++i) scanf("%d", &v[i]);
scanf("%s", s);
int len = strlen(s);
sum1[0] = v[s[0]-'a'];
for(i = 1; i < len; ++i){
sum1[i] = sum1[i-1] + v[s[i]-'a'];
}
strcpy(s1, s);
reverse(s1, s1+len);
sum2[0] = v[s1[0]-'a'];
for(i = 1; i < len; ++i)
sum2[i] = sum2[i-1] + v[s1[i]-'a'];
strcpy(s1, s); s1[len] = '!';   //前缀
strcpy(s1+len+1, s);
reverse(s1+len+1, s1+len+len+1);
// cout<<s1<<endl;
strcpy(s2, s); s2[len] = '!';   //后缀
strcpy(s2+len+1, s);
reverse(s2, s2+len);      //倒置字符串
// cout<<s2<<endl;
memset(rsum, 0, sizeof(rsum));
memset(lsum, 0, sizeof(lsum));
getfail(s1, strlen(s1));
i = strlen(s1);
do{
i = next[i];
rsum[i] = sum1[i-1];  //前缀成回文串的价值和
}while(next[i]);

getfail(s2, strlen(s2));

i = strlen(s2);
do{
i = next[i];
lsum[i] = sum2[i-1];  //后缀成回文串的价值和
}while(next[i]);
int ans = -(1<<30);
for(i = 1; i < len; ++i)
ans = max(ans, rsum[i] + lsum[len-i]);  //遍历求最大值
printf("%d\n",ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: