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).
Source
My Solution
题意:给出k个长度为n的字符串且每个字符串有一个权值,选一些字符串构成一个回文串,使这个回文串的总权值尽可能大,就权值的最大值。
把字符串和权值储存在map<string, vector<int> > mp里,用map<string, bool> flag来标记字符串是否为回文串。
选尽可能多的字符串对x + y > 0,x与y互为回文,且xy都优先选大的,其中分成本身是回文串的和不是回文串2类讨论,
如果本身是回文串,且个数大于2,而且x + y > 0,则也ans += x + y,并判断
如果 x < 0 则 minpadd = min(minpadd, x), 如果y < 0 则 minpadd = min(minpadd, y)
然后遍历flag,找出一个单独的剩余的回文串的正的最大值ansplus。
如果minpadd被维护过,即ans里存在自身为回文串的字符串对且虽然权值和为正数但其中一个权值为负数,
则把-minpadd 与ansplus比较,如果-minpadd 比ansplus大,则把那个回文串对的正的作为构成的大回文串的中心而负的那个去掉,
如果 ansplus更大,值直接加到ans里就好
即if(minpadd != 1) ans += max(-minpadd, ansplus);
如果minpadd没有被维护过,则直接把ansplus加上去, ans += ansplus。
复杂度 O(nk*klogn)
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 8;
string s;
int v;
map<string, vector<int> > mp;
map<string, bool> flag;
int main()
{
#ifdef LOCAL
freopen("d.txt", "r", stdin);
//freopen("d.out", "w", stdout);
int T = 4;
while(T--){
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
int k, n, a, b;
cin >> k >> n;
bool ok;
for(int i = 0; i < k; i++){
cin >> s >> v;
mp[s].push_back(v);
if(mp[s].size() == 1){
ok = true;
for(int j = 0; j < n / 2; j++){
if(s[j] != s[n - 1 - j]){
ok = false;
break;
}
}
if(ok) flag[s] = true;
}
}
for(auto i = mp.begin(); i != mp.end(); i++){
sort((i->second).begin(), (i->second).end());
}
int ans = 0, minpadd = 1, sz;
for(auto i = mp.begin(); i != mp.end(); i++){
s = i->first;
reverse(s.begin(), s.end());
if(s != (i->first)){
while(!mp[s].empty() && !(i->second).empty()){
a = *((i->second).rbegin());
b = *(mp[s].rbegin());
if(a + b > 0){
ans += a + b;
(i->second).pop_back();
mp[s].pop_back();
}
else break;
}
}
else{
sz = mp[s].size();
while(sz >= 2){
a = mp[s][sz-1];
b = mp[s][sz-2];
if(a + b > 0){
ans += a + b;
if(a < 0){
minpadd = min(minpadd, a);
}
else if(b < 0){
minpadd = min(minpadd, b);
}
mp[s].pop_back();
mp[s].pop_back();
sz -= 2;
}
else break;
}
}
}
int ansplus = 0;
for(auto i = flag.begin(); i != flag.end(); i++){
if(mp[i->first].size() > 0){
ansplus = max(ansplus, *(mp[i->first].rbegin()));
}
}
if(minpadd != 1){
ans += max(-minpadd, ansplus);
}
else ans += ansplus;
cout << ans << endl;
#ifdef LOCAL
mp.clear();
flag.clear();
cout << endl;
}
#endif // LOCAL
return 0;
}
Thank you!