2 seconds
256 megabytes
standard input
standard output
Santa Claus likes palindromes very much. There was his birthday recently. k of his friends came to him to congratulate him, and each of them presented to him a string si having the same length n. We denote the beauty of the i-th string by ai. It can happen that ai is negative — that means that Santa doesn't find this string beautiful at all.
Santa Claus is crazy about palindromes. He is thinking about the following question: what is the maximum possible total beauty of a palindrome which can be obtained by concatenating some (possibly all) of the strings he has? Each present can be used at most once. Note that all strings have the same length n.
Recall that a palindrome is a string that doesn't change after one reverses it.
Since the empty string is a palindrome too, the answer can't be negative. Even if all ai's are negative, Santa can obtain the empty string.
The first line contains two positive integers k and n divided by space and denoting the number of Santa friends and the length of every string they've presented, respectively (1 ≤ k, n ≤ 100 000; n·k ≤ 100 000).
k lines follow. The i-th of them contains the string si and its beauty ai ( - 10 000 ≤ ai ≤ 10 000). The string consists of n lowercase English letters, and its beauty is integer. Some of strings may coincide. Also, equal strings can have different beauties.
In the only line print the required maximum possible beauty.
7 3
abb 2
aaa -3
bba -1
zyz -4
abb 5
aaa 7
xyx 4
12
3 1
a 1
a 2
a 3
6
2 5
abcde 10000
abcde 10000
0
In the first example Santa can obtain abbaaaxyxaaabba by concatenating strings 5, 2, 7, 6 and 3 (in this order).
题意:
共有k个字符串,每个长度为n,每个字符串有权值,问用这些字符串能组成的权值最大的回文串,输出权值。可以一个都不用最后权值为0,一个相同的字符串可能对应多个不同的权值。
代码:
//STL好强啊。共有两种情况,本身不是回文串的必须要有他的反串和他一起,本身是回文串的可以将一个放在中间,将一对
//放在两边。由于每个字符串可以由多个权值所以用的时候要尽量用权值大的。把他们放到优先队列中再map,用迭代器遍历,
//操作优先队列。当字符串是回文串并且多于一个时,有可能出现加入的第一个的权值>0,而第二个的权值<0,而此时又没有另
//一个正权值的回文串可以放在中间那么第二个权值<0的就不加入。
#include<bits\stdc++.h>
using namespace std;
char ch[];
struct cmp
{
bool operator()(int &a,int &b){
return a<b;
}
};
map<string,priority_queue<int,vector<int>,cmp> >mp;
int main()
{
int k,n,x;
scanf("%d%d",&k,&n);
for(int i=;i<k;i++){
scanf("%s %d",ch,&x);
string s=ch;
mp[s].push(x);
}
int ans=,maxn=,minn=;
for(map<string,priority_queue<int,vector<int>,cmp> >::iterator it=mp.begin();it!=mp.end();it++){
string s1=it->first;
string s2=s1;
reverse(s2.begin(),s2.end()); //翻转字符串
if(s1!=s2&&mp.find(s2)!=mp.end()){ //非回文串,并且存在相反串
while(!mp[s1].empty()&&!mp[s2].empty()){
int now=mp[s1].top()+mp[s2].top();
if(now>){
ans+=now;
mp[s1].pop();
mp[s2].pop();
}
else break;
}
}
else if(s1==s2){ //是回文串
while(mp[s1].size()>=){
int now1=mp[s1].top();
mp[s1].pop();
int now2=mp[s1].top();
mp[s1].pop();
if(now1+now2>){
ans+=(now1+now2);
minn=min(minn,now2); //记录
}
else{
mp[s1].push(now2);
mp[s1].push(now1);
break;
}
}
}
}
for(map<string,priority_queue<int,vector<int>,cmp> >::iterator it=mp.begin();it!=mp.end();it++){
string s1=it->first;
string s2=s1;
reverse(s2.begin(),s2.end());
if(s1==s2&&!mp[s1].empty()) //找一个放在中间的回文串
maxn=max(maxn,mp[s1].top());
}
printf("%d\n",max(ans-minn,ans+maxn));
return ;
}