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.
#include <bits/stdc++.h>
#define Fori(x) for(int i=0;i<x;i++)
#define Forj(x) for(int j=0;j<x;j++)
#define maxn 5005
#define inf 0x3f3f3f3f
#define ONES(x) __builtin_popcount(x)
using namespace std;
typedef long long ll ;
const double eps =1e-8;
const int mod = 1000000007;
typedef pair<int, int> P;
const double PI = acos(-1.0);
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
int n,k,m;
ll ans;
struct Node{
string s;
int val;
}node[100005];
map<string,multiset<int> > dic;//multiset储存多个相同大小的值
bool cmp(Node a, Node b)
{
return a.val > b.val;
}
int main()
{
freopen("test.txt","r",stdin);
ios_base::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i = 0; i<n; i++)
{
cin>>node[i].s;
cin>>node[i].val;
dic[node[i].s].insert(node[i].val);
}
int k = 0;int x = 0;int temp = 0;
for(int i =0; i<n; i++)
{
string s1 = node[i].s;
int val = (*dic[s1].rbegin());//the last val of the set
if(dic[s1].size()==0)
continue;
if(val<0)
continue;
reverse(s1.begin(),s1.end());//s1->对称字符串
dic[node[i].s].erase(dic[node[i].s].find(val));
if(dic[s1].size()!=0)
{
temp = (*dic[s1].rbegin());//选出配对字符串的最大值
dic[s1].erase(dic[s1].find(temp));
if(val+temp>=0){
ans+=(val+temp);
if(s1==node[i].s)
{
x = max(-temp,x);//将差值加入到中间字符串的选择过程中
}
}
else if(s1==node[i].s)
x = max(x,val);//选择中间的自对称字符串
}
else if(s1==node[i].s)
x = max(x,val);//选择中间的自对称字符串
}
cout << ans+x << endl;//结果补上中间的字符串的值
return 0;
}