#include<bits/stdc++.h>
#define ll  long long int
using namespace std;
#define fio ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define endl "\n"
#define maxpq priority_queue<ll>
#define minpq priority_queue<ll, vector<ll>, greater<ll> >
#define vi vector<ll>
#define pii pair<ll, ll>
#define vii vector<pii>
#define for0(i, n) for (int i = 0; i < n; i++)
#define for1(i, n) for (int i = 1; i <= n; i++)
#define loop(i,a,b) for (int i = a; i < b; i++)
#define bloop(i,a,b) for (int i = a ; i>=b;i--)
#define MOD 1000000007
#define INT_MAXI 9000000000000000000
#define INT_MINI -9000000000000000000

ll max(ll a, ll b) {if (a > b) return a; else return b;}
ll min(ll a, ll b) {if (a < b) return a; else return b;}

const int dx[4] = { -1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};
int XX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
int YY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

map<ll,vector<ll> >mpp;
map<ll,ll>mpp2;
set<ll>s,s2;

ll func(string str)
{
	ll hash=0,p=1;
	for(ll i=0;i<str.length();i++)
	{
		hash=(hash+((str[i]-'a'+1)*p)%MOD)%MOD;
		p*=31;
		p%=MOD;
	}
	return hash;

}

int main()
{

	fio;

	ll k,n,i,j,val;
	cin>>k>>n;
	for(i=0;i<k;i++)
	{
		string str;
		cin>>str>>val;
		ll hash=func(str);

		s.insert(hash);

		mpp[hash].pb(val);
		reverse(str.begin(),str.end());
		ll hash2=func(str);
		mpp2[hash]=hash2;
		mpp2[hash2]=hash;

	}
	ll ans=0,maxi=0;
	while(!s.empty())
	{
		vi vec1,vec2;
		auto itr=s.begin();
		ll x=mpp2[(*itr)];
		s.erase((*itr));
		if(s.find(x)!=s.end())
		s.erase(x);
		if(mpp[(*itr)].size()!=0)
		vec1=mpp[(*itr)];
		if(mpp[x].size()!=0)
		vec2=mpp[x];
		if(vec1.size()!=0)
		sort(vec1.begin(),vec1.end(),greater<ll>());
		if(vec2.size()!=0)
		sort(vec2.begin(),vec2.end(),greater<ll>());
		if((*itr)==x)
		{
			for(i=0;i<vec1.size()-1;i+=2)
			{
				if(vec1[i]+vec1[i+1]>0)
				ans+=(vec1[i]+vec1[i+1]);
				else
				break;
			}
			if(i<vec1.size()&&vec1[i]>0)
			{
				maxi=max(maxi,vec1[i]);
			}
		}
		else
		{
			i=0,j=0;
			while(i<vec1.size()&&j<vec2.size()&&vec1[i]+vec2[j]>0)
			{
				ans+=vec1[i]+vec2[j];
				i++;
				j++;
			}
		}

	}
	ans+=maxi;
	cout<<ans;

}


#include<bits/stdc++.h>
#define ll  long long int
using namespace std;
#define fio ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define endl "\n"
#define maxpq priority_queue<ll>
#define minpq priority_queue<ll, vector<ll>, greater<ll> >
#define vi vector<ll>
#define pii pair<ll, ll>
#define vii vector<pii>
#define for0(i, n) for (int i = 0; i < n; i++)
#define for1(i, n) for (int i = 1; i <= n; i++)
#define loop(i,a,b) for (int i = a; i < b; i++)
#define bloop(i,a,b) for (int i = a ; i>=b;i--)
#define MOD 1000000007
#define INT_MAXI 9000000000000000000
#define INT_MINI -9000000000000000000

ll max(ll a, ll b) {if (a > b) return a; else return b;}
ll min(ll a, ll b) {if (a < b) return a; else return b;}

const int dx[4] = { -1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};
int XX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
int YY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

map<ll,vector<ll> >mpp;
map<ll,ll>mpp2;
set<ll>s,s2;

ll func(string str)
{
	ll hash=0,p=1;
	for(ll i=0;i<str.length();i++)
	{
		hash=(hash+((str[i]-'a'+1)*p)%MOD)%MOD;
		p*=31;
		p%=MOD;
	}
	return hash;

}

int main()
{

	fio;

	ll k,n,i,j,val;
	cin>>k>>n;
	for(i=0;i<k;i++)
	{
		string str;
		cin>>str>>val;
		ll hash=func(str);

		s.insert(hash);

		mpp[hash].pb(val);
		reverse(str.begin(),str.end());
		ll hash2=func(str);
		mpp2[hash]=hash2;
		mpp2[hash2]=hash;

	}
	ll ans=0,maxi=0;
	while(!s.empty())
	{
		vi vec1,vec2;
		auto itr=s.begin();
		ll x=mpp2[(*itr)];
		s.erase((*itr));
		if(s.find(x)!=s.end())
		s.erase(x);
		if(mpp[(*itr)].size()!=0)
		{
		    for(i=0;i<mpp[(*itr)].size();i++)
		    vec1.pb(mpp[(*itr)][i]);
		}

		if(mpp[x].size()!=0)
		{
		    for(i=0;i<mpp[x].size();i++)
		    vec2.pb(mpp[x][i]);
		}

		if(vec1.size()!=0)
		sort(vec1.begin(),vec1.end(),greater<ll>());
		if(vec2.size()!=0)
		sort(vec2.begin(),vec2.end(),greater<ll>());
		if((*itr)==x)
		{
			for(i=0;i<vec1.size()-1;i+=2)
			{
				if(vec1[i]+vec1[i+1]>0)
				ans+=(vec1[i]+vec1[i+1]);
				else
				break;
			}
			if(i<vec1.size()&&vec1[i]>0)
			{
				maxi=max(maxi,vec1[i]);
			}
		}
		else
		{
			i=0,j=0;
			while(i<vec1.size()&&j<vec2.size()&&vec1[i]+vec2[j]>0)
			{
				ans+=vec1[i]+vec2[j];
				i++;
				j++;
			}
		}

	}
	ans+=maxi;
	cout<<ans;

}


#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;

constexpr int B = 33, M = 1000000000 + 3337;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int k, n;
    cin >> k >> n;
    vector<pair<int, string>> a(k);
    for(int i = 0; i < k; ++i) {
        cin >> a[i].se >> a[i].fi;
    }
    sort(a.rbegin(), a.rend());
    map<int, priority_queue<int>> words, pals;

    int ans = 0;
    for(auto & x : a) {
        string & s = x.se;
        int beauty = x.fi;

        int f = 0, b = 0;
        for(int i = 0, p = 1; i < n; ++i, p = 1ll * p * B % M) {
            f += 1ll * (s[i] - 'a') * p % M;
            if(f >= M) f -= M;
            b = 1ll * b * B % M + (s[i] - 'a');
            if(b >= M) b -= M;
        }

        if(f != b) {
            bool matched = false;
            if(words.find(f) != words.end()) {
                priority_queue<int> & pq = words[f];
                if(!pq.empty() && pq.top() + beauty > 0) {
                    ans += pq.top() + beauty;
                    pq.pop();
                    matched = true;
                }
            }
            if(!matched) {
                words[b].push(beauty);
            }
        } else {
            pals[f].push(beauty);
        }
    }

    vector<int> left;
    vector<pair<int, int>> pr;
    for(auto& x: pals) {
        priority_queue<int> & pq = x.se;
        while(true) {
            if(pq.size() == 0) break;
            if(pq.size() == 1) {
                if(pq.top() > 0) left.push_back(pq.top());
                break;
            }
            int a = pq.top(); pq.pop();
            int b = pq.top(); pq.pop();
            if(a < 0) break;
            if(b > 0) {
                ans += a + b;
                continue;
            }
            pr.push_back({a, b});
        }
    }

    if(left.size()) {
        ans += *max_element(left.begin(), left.end());
        for(auto& x: pr) ans += max(0, x.fi + x.se);
    } else {
        sort(pr.begin(), pr.end(), [](auto & x, auto & y) {
                                       return x.fi + x.se < y.fi + y.se;
                                   });
        while(pr.size() > 1 && pr.back().fi + pr.back().se > 0) {
            ans += pr.back().fi + pr.back().se;
            pr.pop_back();
        }
        if(pr.size()) {
            ans += max_element(pr.begin(), pr.end())->fi;
        }
    }

    cout << ans << '\n';
}


#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;

constexpr int B = 33, M = 1000000000 + 3337;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int k, n;
    cin >> k >> n;
    vector<pair<int, string>> a(k);
    for(int i = 0; i < k; ++i) {
        cin >> a[i].se >> a[i].fi;
    }
    sort(a.rbegin(), a.rend());
    map<int, priority_queue<int>> words, pals;

    int ans = 0;
    for(auto & x : a) {
        string & s = x.se;
        int beauty = x.fi;

        int f = 0, b = 0;
        for(int i = 0, p = 1; i < n; ++i, p = 1ll * p * B % M) {
            f += 1ll * (s[i] - 'a') * p % M;
            if(f >= M) f -= M;
            b = 1ll * b * B % M + (s[i] - 'a');
            if(b >= M) b -= M;
        }

        if(f != b) {
            bool matched = false;
            if(words.find(f) != words.end()) {
                priority_queue<int> & pq = words[f];
                if(!pq.empty() && pq.top() + beauty > 0) {
                    ans += pq.top() + beauty;
                    pq.pop();
                    matched = true;
                }
            }
            if(!matched) {
                words[b].push(beauty);
            }
        } else {
            pals[f].push(beauty);
        }
    }

    int left = 0;
    vector<pair<int, int>> pr;
    for(auto& x: pals) {
        priority_queue<int> & pq = x.se;
        while(true) {
            if(pq.size() == 0) break;
            if(pq.size() == 1) {
                left = max(left, pq.top());
                break;
            }
            int a = pq.top(); pq.pop();
            int b = pq.top(); pq.pop();
            if(a < 0) break;
            if(b > 0) {
                ans += a + b;
                continue;
            }
            pr.push_back({a, b});
        }
    }

    int sum = 0;
    for(auto & x : pr) {
        sum += max(0, x.fi + x.se);
    }

    int part = left + sum;
    for(auto & x : pr) {
        part = max(part, x.fi + sum - max(0, x.fi + x.se));
    }

    cout << ans + part << '\n';
}


#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;

constexpr int B = 33, M = 1000000000 + 3337;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int k, n;
    cin >> k >> n;
    vector<pair<int, string>> a(k);
    for(int i = 0; i < k; ++i) {
        cin >> a[i].se >> a[i].fi;
    }
    sort(a.rbegin(), a.rend());
    map<int, priority_queue<int>> words;
    multiset<int> pals;

    int ans = 0;
    for(auto & x : a) {
        string & s = x.se;
        int beauty = x.fi;

        int f = 0, b = 0;
        for(int i = 0, p = 1; i < n; ++i, p = 1ll * p * B % M) {
            f += 1ll * (s[i] - 'a') * p % M;
            if(f >= M) f -= M;
            b = 1ll * b * B % M + (s[i] - 'a');
            if(b >= M) b -= M;
        }

        bool matched = false;
        if(words.find(f) != words.end()) {
            priority_queue<int> & pq = words[f];
            if(!pq.empty() && pq.top() + beauty > 0) {
                int match_beauty = pq.top();
                pq.pop();
                ans += match_beauty + beauty;
                matched = true;
                if(f == b) {
                    pals.erase(pals.find(match_beauty));
                }
            }
        }
        if(!matched) {
            words[b].push(beauty);
            if(f == b) {
                pals.insert(beauty);
            }
        }
    }
    if(pals.size()) {
        auto it = prev(pals.end());
        if(*it > 0) ans += *it;
    }
    cout << ans << '\n';
}


#include <bits/stdc++.h>
#define ll long long int

using namespace std;

const ll MOD = 998244353 ;

bool is_palindrome(const string & s){
    for(int i = 0; i < s.size()/2; ++i){
        if( s[i] != s[s.size() - 1 - i] )
            return false;
    }
    return true;
}

void solve(){
    vector<pair<int, string>> a;
    multiset<pair<string, int>> st;
    map<string, string> inv;
    int k, n;
    cin >> k >> n;
    for(int i = 0; i < k; ++i){
        string s; int c;
        cin >> s >> c;
        a.emplace_back(c, s);
        inv[s] = string(s.rbegin(), s.rend());
    }
    sort(a.begin(), a.end(), greater<pair<int, string>>());
    int ans = 0, middle = 0;
    for(auto p: a){
        auto it = st.lower_bound({inv[p.second], INT_MIN});
        //Now check if there is a reverse of a i.e b is possible to find or not
        //if found -> check if their sum a + b is positive.
        //if not positive. add it in set of traversed strings which are unpaired
        //and in untraversed set of strings, i am inserting negative of it.
        //so whenever i do lower bound i get max value of that string which is untaken.
        if( it != st.end() and !inv[p.second].compare(it->first) and p.first - it->second > 0 ){
            ans += p.first - (it->second);
            st.erase(it);
            if(is_palindrome(p.second) and p.first < 0) middle = max(-p.first, middle);
        } else {
            st.emplace(p.second, -p.first);
        }
    }
    for(auto p : st){
        if( is_palindrome(p.first) ) middle = max(-p.second, middle);
    }
    cout << ans + middle << '\n';
}

int main(){
    //int t; cin >> t;
    //while(t--)
        solve();
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=31;
int const pri2=29;

int64_t encode(int64_t l, int64_t r) {
	return (l<<27)|r;
}

void decode(int64_t h, int &l, int &r) {
	int64_t a = h>>27;
	int64_t b = h-(a<<27);
	l=(int)a;
	r=(int)b;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l1=0, l2=0, r1=0, r2=0, p1=1, p2=1;
		for (int j=0; j<n; j++) {
			l1 += p1*(s[j]-'a'+1);
			p1 *= pri1;
			l2 += p2*(s[j]-'a'+1);
			p2 *= pri2;

			r1 *= pri1;
			r1 += (s[j]-'a'+1);
			r2 *= pri2;
			r2 += (s[j]-'a'+1);
		}
		int64_t l = encode(l1, l2);
		int64_t r = encode(r1, r2);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int64_t const pri=151;
int64_t const mod=1000000007;

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int64_t l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l = (l+p*s[j]%mod)%mod;
			p = p*pri%mod;
			r = r*pri%mod;
			r = (r+s[j])%mod;
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=151;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> singles;
vector<pair<int, int>> doubles;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>0; j+=2) {
				if (j+1==v.size() || (v[j+1]<0 && v[j]<=-v[j+1]))
					singles.emplace_back(v[j]);
				else if (v[j+1]>=0)
					sum+=v[j]+v[j+1];
				else
					doubles.emplace_back(make_pair(v[j], v[j+1]));
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0) {
				if (v[iv]+r[ir]>0)
					sum+=v[iv]+r[ir];
				iv++; ir++;
			}

			tag[rev[i.first]]=true;
		}
	}

	int alldoubles=0;
	for (const auto &i:doubles)
		alldoubles+=i.first+i.second;

	sum+=alldoubles;
	int maxsum=sum;
	for (const auto &i:doubles) {
		maxsum=max(sum-i.second, maxsum);
	}

	for (const auto &i:singles)
		maxsum=max(sum+i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=151;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> singles;
vector<pair<int, int>> doubles;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>0; j+=2) {
				if (j+1==v.size()) {
					if (v[j]>0)
						singles.emplace_back(v[j]);
				}
				else if (v[j+1]>=0)
					sum+=v[j]+v[j+1];
				else if (v[j]+v[j+1]>0)
					doubles.emplace_back(make_pair(v[j], v[j+1]));
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0) {
				if (v[iv]>=0&&r[ir]>=0)
					sum+=v[iv]+r[ir];
				else {
					int pos=v[iv], neg=r[ir];
					if (v[iv]<0) {
						neg=pos;
						pos=r[ir];
					}
					doubles.emplace_back(make_pair(pos, neg));
				}
				iv++; ir++;
			}

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=0, alldoubles=0;
	for (const auto &i:doubles) {
		alldoubles+=i.first+i.second;
		maxsum=max(sum+i.first, maxsum);
	}

	sum+=alldoubles;
	maxsum=max(maxsum, sum);
	for (const auto &i:singles)
		maxsum=max(sum+i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}

/*
 int n=(int)strlen(s), r=s[0], l=s[0], sum=1, p=1;

 for (int i=1; i<n; i++) {
 p *= pri;
 l += p*s[i];
 r *= pri;
 r += s[i];
 if (l==r) {
 deg[i]=1+deg[((i+1)>>1)-1];
 sum += deg[i];
 }
 }

 */


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=31;
int const pri2=29;
int const mod1=1000000009;
int const mod2=1000000007;

int64_t encode(int64_t l, int64_t r) {
	return (l<<27)|r;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int64_t l1=0, l2=0, r1=0, r2=0, p1=1, p2=1;
		for (int j=0; j<n; j++) {
			l1 = (l1+p1*(s[j]-'a'+1)%mod1)%mod1;
			p1 = p1*pri1%mod1;
			l2 = (l2+p2*(s[j]-'a'+1)%mod2)%mod2;
			p2 = p2*pri2%mod2;

			r1 = r1*pri1%mod1;
			r1 = (r1+(s[j]-'a'+1))%mod1;
			r2 = r2*pri2%mod2;
			r2 = (r2+(s[j]-'a'+1))%mod2;
		}
		int64_t l = encode(l1, l2);
		int64_t r = encode(r1, r2);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=131;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> singles;
vector<pair<int, int>> doubles;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || ((v[j+1]<0) && (-v[j+1]>=v[j])))
					singles.emplace_back(v[j]);
				else if (v[j+1]>=0)
					sum+=v[j]+v[j+1];
				else
					doubles.emplace_back(make_pair(v[j], v[j+1]));
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	for (const auto &i:doubles)
		sum+=i.first+i.second;

	int maxsum=sum;
	for (const auto &i:doubles)
		maxsum=max(sum-i.second, maxsum);

	for (const auto &i:singles)
		maxsum=max(sum+i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=131;
int const pri2=29;

int64_t encode(int64_t l, int64_t r) {
	return (l<<31)|r;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	freopen("a.in", "r", stdin);
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l1=0, l2=0, r1=0, r2=0, p1=1, p2=1;
		for (int j=0; j<n; j++) {
			l1 += p1*(s[j]-'a'+1);
			p1 *= pri1;
			l2 += p2*(s[j]-'a'+1);
			p2 *= pri2;

			r1 *= pri1;
			r1 += (s[j]-'a'+1);
			r2 *= pri2;
			r2 += (s[j]-'a'+1);
		}
		int64_t l = encode(l1, l2);
		int64_t r = encode(r1, r2);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=131;

char s[MAX];
unordered_map<string, bool> tag;
unordered_map<string, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(const string &s) {
	int n = (int)s.length();
	for (int i=0,j=n-1; i<j; i++,j--)
		if (s[i]!=s[j])
			return false;
	return true;
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);
		string str(s);
		val[str].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			string rev= string(i.first.rbegin(), i.first.rend());
			auto &r=val[rev];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int64_t const pri=151;

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int64_t l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=131;
int const pri2=29;

int64_t encode(int64_t l, int64_t r) {
	return (l<<32)|r;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l1=0, l2=0, r1=0, r2=0, p1=1, p2=1;
		for (int j=0; j<n; j++) {
			l1 += p1*(s[j]-'a'+1);
			p1 *= pri1;
			l2 += p2*(s[j]-'a'+1);
			p2 *= pri2;

			r1 *= pri1;
			r1 += (s[j]-'a'+1);
			r2 *= pri2;
			r2 += (s[j]-'a'+1);
		}
		int64_t l = encode(l1, l2);
		int64_t r = encode(r1, r2);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=131;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=131;
int const pri2=29;

int64_t encode(int64_t l, int64_t r) {
	return (l<<27)|r;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l1=0, l2=0, r1=0, r2=0, p1=1, p2=1;
		for (int j=0; j<n; j++) {
			l1 += p1*(s[j]-'a'+1);
			p1 *= pri1;
			l2 += p2*(s[j]-'a'+1);
			p2 *= pri2;

			r1 *= pri1;
			r1 += (s[j]-'a'+1);
			r2 *= pri2;
			r2 += (s[j]-'a'+1);
		}
		int64_t l = encode(l1, l2);
		int64_t r = encode(r1, r2);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=151;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> singles;
vector<pair<int, int>> doubles;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += s[j]*p;
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		if (l!=r)
			rev[r]=l;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>0; j+=2) {
				if (j+1==v.size()) {
					if (v[j]>0)
						singles.emplace_back(v[j]);
				}
				else if (v[j+1]>=0)
					sum+=v[j]+v[j+1];
				else if (v[j]+v[j+1]>0)
					doubles.emplace_back(make_pair(v[j], v[j+1]));
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0) {
				if (v[iv]>=0&&r[ir]>=0)
					sum+=v[iv]+r[ir];
				else {
					int pos=v[iv], neg=r[ir];
					if (v[iv]<0) {
						neg=pos;
						pos=r[ir];
					}
					doubles.emplace_back(make_pair(pos, neg));
				}
				iv++; ir++;
			}

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=0, alldoubles=0;
	for (const auto &i:doubles) {
		alldoubles+=i.first+i.second;
		maxsum=max(sum+i.first, maxsum);
	}

	sum+=alldoubles;
	for (const auto &i:singles)
		maxsum=max(sum+i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=131;
int const pri2=29;
int const pri3=151;

int64_t encode(int64_t l, int64_t r, int64_t t) {
	return ((l<<32)|r)*t;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l1=0, l2=0, r1=0, r2=0, p1=1, p2=1, p3=1, l3=0, r3=0;
		for (int j=0; j<n; j++) {
			l1 += p1*(s[j]-'a'+1);
			p1 *= pri1;
			l2 += p2*(s[j]-'a'+1);
			p2 *= pri2;
			l3 += p3*(s[j]-'a'+1);
			p3 *= pri3;

			r1 *= pri1;
			r1 += (s[j]-'a'+1);
			r2 *= pri2;
			r2 += (s[j]-'a'+1);
			r3 *= pri3;
			r3 += (s[j]-'a'+1);
		}
		int64_t l = encode(l1, l2, l3);
		int64_t r = encode(r1, r2, r3);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=31;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*(s[j]-'a'+1);
			p *= pri;
			r *= pri;
			r += (s[j]-'a'+1);
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri1=131;
int const pri2=29;

int64_t encode(int64_t l, int64_t r) {
	return (l<<31)|r;
}

char s[MAX];

unordered_map<int64_t, int64_t> rev;
unordered_map<int64_t, bool> tag;
unordered_map<int64_t, vector<int>> val;
vector<int> neg_pair;

const inline bool ispalin(int64_t n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	int maxsingle=0;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l1=0, l2=0, r1=0, r2=0, p1=1, p2=1;
		for (int j=0; j<n; j++) {
			l1 += p1*(s[j]-'a'+1);
			p1 *= pri1;
			l2 += p2*(s[j]-'a'+1);
			p2 *= pri2;

			r1 *= pri1;
			r1 += (s[j]-'a'+1);
			r2 *= pri2;
			r2 += (s[j]-'a'+1);
		}
		int64_t l = encode(l1, l2);
		int64_t r = encode(r1, r2);
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>=0; j+=2) {
				if (j+1==v.size() || -v[j+1]>=v[j])
					maxsingle=max(maxsingle, v[j]);
				else {
					sum+=v[j]+v[j+1];
					if (v[j+1]<0)
						neg_pair.emplace_back(v[j+1]);
				}
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0)
				sum+=v[iv++]+r[ir++];

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=sum+maxsingle;
	for (const auto &i:neg_pair)
		maxsum=max(sum-i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=151;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> singles;
vector<pair<int, int>> doubles;

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>0; j+=2) {
				if (j+1==v.size()) {
					if (v[j]>0)
						singles.emplace_back(v[j]);
				}
				else if (v[j+1]>=0)
					sum+=v[j]+v[j+1];
				else if (v[j]+v[j+1]>0)
					doubles.emplace_back(make_pair(v[j], v[j+1]));
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0) {
				if (v[iv]+r[ir]>0)
					sum+=v[iv]+r[ir];
				iv++; ir++;
			}

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=0, alldoubles=0;
	for (const auto &i:doubles) {
		alldoubles+=i.first+i.second;
		maxsum=max(sum+i.first, maxsum);
	}

	sum+=alldoubles;
	maxsum=max(maxsum, sum);
	for (const auto &i:singles)
		maxsum=max(sum+i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}

/*
 int n=(int)strlen(s), r=s[0], l=s[0], sum=1, p=1;

 for (int i=1; i<n; i++) {
 p *= pri;
 l += p*s[i];
 r *= pri;
 r += s[i];
 if (l==r) {
 deg[i]=1+deg[((i+1)>>1)-1];
 sum += deg[i];
 }
 }

 */


#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int MAX=111111;
int const pri=151;

char s[MAX];

unordered_map<int, int> rev;
unordered_map<int, bool> tag;
unordered_map<int, vector<int>> val;
vector<int> singles;
vector<pair<int, int>> doubles[2];

const inline bool ispalin(int n) {
	return n == rev[n];
}

int main() {
	int sum=0, n, k;
	scanf("%d%d", &k,&n);
	for (int i=0, v; i<k; i++) {
		scanf("%s%d", s, &v);

		int l=0, r=0, p=1;
		for (int j=0; j<n; j++) {
			l += p*s[j];
			p *= pri;
			r *= pri;
			r += s[j];
		}
		rev[l]=r;
		val[l].emplace_back(v);
	}

	for (auto &i:val) {
		if (tag[i.first])
			continue;

		auto &v=i.second;
		sort(v.rbegin(), v.rend());

		if (ispalin(i.first)) {
			for (int j=0; j<v.size()&&v[j]>0; j+=2) {
				if (j+1==v.size()) {
					if (v[j]>0)
						singles.emplace_back(v[j]);
				}
				else if (v[j+1]>=0)
					sum+=v[j]+v[j+1];
				else if (v[j]+v[j+1]>0)
					doubles[1].emplace_back(make_pair(v[j], v[j+1]));
			}
		}
		else {
			auto &r=val[rev[i.first]];
			sort(r.rbegin(), r.rend());

			int iv=0,ir=0;
			while (iv<v.size()&&ir<r.size()&&v[iv]+r[ir]>0) {
				if (v[iv]>=0&&r[ir]>=0)
					sum+=v[iv]+r[ir];
				else {
					int pos=v[iv], neg=r[ir];
					if (v[iv]<0) {
						neg=pos;
						pos=r[ir];
					}
					doubles[0].emplace_back(make_pair(pos, neg));
				}
				iv++; ir++;
			}

			tag[rev[i.first]]=true;
		}
	}

	int maxsum=0, alldoubles=0;
	for (const auto &i:doubles[0])
		alldoubles+=i.first+i.second;

	sum+=alldoubles;
	alldoubles=0;
	for (const auto &i:doubles[1]) {
		alldoubles+=i.first+i.second;
		maxsum=max(sum+i.first, maxsum);
	}

	sum+=alldoubles;
	maxsum=max(maxsum, sum);
	for (const auto &i:singles)
		maxsum=max(sum+i, maxsum);

	printf("%d\n", maxsum);

	return 0;
}

/*
 int n=(int)strlen(s), r=s[0], l=s[0], sum=1, p=1;

 for (int i=1; i<n; i++) {
 p *= pri;
 l += p*s[i];
 r *= pri;
 r += s[i];
 if (l==r) {
 deg[i]=1+deg[((i+1)>>1)-1];
 sum += deg[i];
 }
 }

 */


#include <iostream>
#include <string>
#include <algorithm>
#include <math.h>
#include <vector>
#include <iomanip>
#include <unordered_map>

using namespace std;

const int N = 1e5 + 5;
#define ll long long
string st,ne;
ll p_pow[N];
int n,k;

ll p = 31, m = 1e9 + 9;
string s;
ll hsh(){
    ll ret = 0;
    for (int i = 0; i < k; i++) {
        ret = (ret + p_pow[i + 1] * s[i]) % m;
    }
    return ret;
}

void capow(){
    p_pow[0] = 1;
    for (int i = 1; i <= k; i++) {
        p_pow[i] = (p_pow[i - 1] * p) % m;
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> k;
    capow();
    unordered_map<ll, pair<ll, vector<ll>>> se;
    unordered_map<ll, vector<ll>> re;
    unordered_map<ll, vector<ll>> pal;
    for (int i = 0; i < n; i++) {
        int a;
        cin >> s >> a;
        ll h = hsh();
        reverse(s.begin(), s.end());
        ll h2 = hsh();
        if(h == h2){
            pal[h].push_back(a);
        }
        else if(se.find(h) == se.end() && re.find(h) == re.end()){
            se[h].second.push_back(a);
            se[h].first = h2;
            re[h2].push_back(-123456789);
        }
        else if(se.find(h) != se.end()){
            se[h].second.push_back(a);
        }
        else{
            re[h].push_back(a);
        }
    }
    ll cnt = 0;
    vector<ll> st;
    vector<ll> en;
    for (auto x: se) {
        if(re.find(x.second.first) != re.end()){
            st = x.second.second;
            en = re[x.second.first];
            sort(st.begin(), st.end());
            sort(en.begin(), en.end());
            reverse(st.begin(), st.end());
            reverse(en.begin(), en.end());
            for (int i = 0; i < min(st.size(), en.size()); i++) {
                if(st[i] + en[i] > 0){
                    cnt += st[i] + en[i];
                }
                else break;
            }
        }
    }
    ll mx = 0;
    for (auto x: pal) {
        st = x.second;
        sort(st.begin(), st.end());
        reverse(st.begin(), st.end());
        int i = 0;
        while(i < st.size() - 1 && st[i] + st[i + 1] > 0){
            cnt += st[i] + st[i + 1];
            i += 2;
        }
        if (i < st.size()) mx = max(mx, st[i]);
    }
    cnt += mx;
    cout << cnt << endl;
    return 0;
}


#include <iostream>
#include <string>
#include <algorithm>
#include <math.h>
#include <vector>
#include <iomanip>
#include <unordered_map>

using namespace std;

const int N = 1e5 + 5;
#define ll long long
string st,ne;
ll p_pow[N];
int n,k;

ll p = 31, m = 1e9 + 9;
string s;
ll hsh(){
    ll ret = 0;
    for (int i = 0; i < k; i++) {
        ret = (ret + p_pow[i + 1] * (s[i] - 'a' + 1)) % m;
    }
    return ret;
}

void capow(){
    p_pow[0] = 1;
    for (int i = 1; i <= k; i++) {
        p_pow[i] = (p_pow[i - 1] * p) % m;
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> k;
    capow();
    unordered_map<ll, pair<ll, vector<ll>>> se;
    unordered_map<ll, vector<ll>> re;
    unordered_map<ll, vector<ll>> pal;
    for (int i = 0; i < n; i++) {
        int a;
        cin >> s >> a;
        ll h = hsh();
        reverse(s.begin(), s.end());
        ll h2 = hsh();
        if(h == h2){
            pal[h].push_back(a);
        }
        else if(se.find(h) == se.end() && re.find(h) == re.end()){
            se[h].second.push_back(a);
            se[h].first = h2;
            re[h2].push_back(-123456789);
        }
        else if(se.find(h) != se.end()){
            se[h].second.push_back(a);
        }
        else{
            re[h].push_back(a);
        }
    }
    ll cnt = 0;
    vector<ll> st;
    vector<ll> en;
    for (auto x: se) {
        if(re.find(x.second.first) != re.end()){
            st = x.second.second;
            en = re[x.second.first];
            sort(st.begin(), st.end());
            sort(en.begin(), en.end());
            reverse(st.begin(), st.end());
            reverse(en.begin(), en.end());
            for (int i = 0; i < min(st.size(), en.size()); i++) {
                if(st[i] + en[i] > 0){
                    cnt += st[i] + en[i];
                }
                else break;
            }
        }
    }
    ll mx = 0;
    vector<pair<int,int>> v;
    for (auto x: pal) {
        st = x.second;
        sort(st.begin(), st.end());
        reverse(st.begin(), st.end());
        int i = 0;
        while(i < st.size() - 1 && !(st[i + 1] < 0)){
            cnt += st[i] + st[i + 1];
            i += 2;
        }
        if (i < st.size() - 1 && st[i + 1] + st[i] > 0){
            v.push_back(make_pair(-st[i + 1], st[i]));
        }
        else if(i < st.size() && st[i] > 0){
            mx = max(mx, st[i]);
        }
    }
    sort(v.begin(), v.end());
    reverse(v.begin(), v.end());
    int start = 0;
    if(v.size() > 0){
        if(mx > v[0].first){
        cnt += mx;
    }
    else{
        start = 1;
        cnt += v[0].second;
    }
    }
    else{
        cnt += mx;
    }
    for (int i = start; i < v.size(); i++) {
        cnt += v[i].second - v[i].first;
    }
    cout << cnt << endl;
    return 0;
}


#include <iostream>
#include <string>
#include <algorithm>
#include <math.h>
#include <vector>
#include <iomanip>
#include <unordered_map>

using namespace std;

const int N = 1e5 + 5;
#define ll long long
string st,ne;
ll p_pow[N];
int n,k;

ll p = 31, m = 1e9 + 9;
string s;
ll hsh(){
    ll ret = 0;
    for (int i = 0; i < k; i++) {
        ret = (ret + p_pow[i + 1] * (s[i] - 'a' + 1)) % m;
    }
    return ret;
}

void capow(){
    p_pow[0] = 1;
    for (int i = 1; i <= k; i++) {
        p_pow[i] = (p_pow[i - 1] * p) % m;
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> k;
    capow();
    unordered_map<ll, pair<ll, vector<ll>>> se;
    unordered_map<ll, vector<ll>> re;
    unordered_map<ll, vector<ll>> pal;
    for (int i = 0; i < n; i++) {
        int a;
        cin >> s >> a;
        ll h = hsh();
        reverse(s.begin(), s.end());
        ll h2 = hsh();
        if(h == h2){
            pal[h].push_back(a);
        }
        else if(se.find(h) == se.end() && re.find(h) == re.end()){
            se[h].second.push_back(a);
            se[h].first = h2;
            re[h2].push_back(-123456789);
        }
        else if(se.find(h) != se.end()){
            se[h].second.push_back(a);
        }
        else{
            re[h].push_back(a);
        }
    }
    ll cnt = 0;
    vector<ll> st;
    vector<ll> en;
    for (auto x: se) {
        if(re.find(x.second.first) != re.end()){
            st = x.second.second;
            en = re[x.second.first];
            sort(st.begin(), st.end());
            sort(en.begin(), en.end());
            reverse(st.begin(), st.end());
            reverse(en.begin(), en.end());
            for (int i = 0; i < min(st.size(), en.size()); i++) {
                if(st[i] + en[i] > 0){
                    cnt += st[i] + en[i];
                }
                else break;
            }
        }
    }
    ll mx = 0;
    for (auto x: pal) {
        st = x.second;
        sort(st.begin(), st.end());
        reverse(st.begin(), st.end());
        int i = 0;
        while(i < st.size() - 1 && st[i] + st[i + 1] > 0){
            cnt += st[i] + st[i + 1];
            i += 2;
        }
        if (i < st.size()) mx = max(mx, st[i]);
    }
    cnt += mx;
    cout << cnt << endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int HB = 359, HM = 1'000'000'033;
int n;
int add(int a, int b){
	return (a + b) % HM;
}
int mul(int a, int b){
	return (long long) a * b % HM;
}
int hsh(string s){
	int ans = 0;
	for(int i = 0; i < n; i++){
		ans = add(mul(HB, ans), s[i]);
	}
	return ans;
}
int rev_hash(string s){
	reverse(s.begin(), s.end());
	return hsh(s);
}
map<int, int> revh;
map<int, vector<int>> cnth;
int solve(vector<pair<int, int>> v){
	int sum = 0;
	int m = v.size();
	for(int i = 0; i < m; i++) sum += v[i].first;
	int best = sum;
	for(int i = 0; i < m; i++){
		int cur_sum = sum - v[i].first + v[i].second;
		best = max(best, cur_sum);
	}
	return best;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	string s;
	int k, a;
	cin >> k >> n;
	for(int i = 0; i < k; i++){
		cin >> s >> a;
		int ch = hsh(s);
		cnth[ch].push_back(a);
		revh[ch] = rev_hash(s);
	}
	int ans = 0;
	for(auto &p : revh){
		int first_hash = p.first;
		int second_hash = p.second;
		if(first_hash >= second_hash) continue;
		vector<int> &v1 = cnth[first_hash];
		vector<int> &v2 = cnth[second_hash];
		sort(v1.begin(), v1.end(), greater<int>());
		sort(v2.begin(), v2.end(), greater<int>());
		for(int i = 0; i < v1.size() && i < v2.size(); i++){
			if(v1[i] + v2[i] > 0) ans += v1[i] + v2[i];
		}
	}
	vector<pair<int, int>> sol;
	for(auto &p : revh){
		int first_hash = p.first;
		int second_hash = p.second;
		if(first_hash != second_hash) continue;
		vector<int> &v = cnth[first_hash];
		sort(v.begin(), v.end(), greater<int>());
		int sol_even = 0;
		for(int i = 0; i + 1 < v.size(); i += 2){
			if(v[i] + v[i + 1] > 0){
				sol_even += v[i] + v[i + 1];
			} else break;
		}
		int sol_odd = 0;
		if(v[0] > 0){
			sol_odd += v[0];
			for(int i = 1; i < v.size(); i += 2){
				if(v[i] + v[i + 1] > 0){
					sol_odd += v[i] + v[i + 1];
				} else break;
			}
		}
		sol.push_back({sol_even, sol_odd});
	}
	ans += solve(sol);
	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int HB = 359, HM = 1'000'000'009;
int n;
int add(int a, int b){
	return (a + b) % HM;
}
int mul(int a, int b){
	return (long long) a * b % HM;
}
int hsh(string s){
	int ans = 0;
	for(int i = 0; i < n; i++){
		ans = add(mul(HB, ans), s[i]);
	}
	return ans;
}
int rev_hash(string s){
	reverse(s.begin(), s.end());
	return hsh(s);
}
map<int, int> revh;
map<int, vector<int>> cnth;
int solve(vector<pair<int, int>> v){
	int sum = 0;
	int m = v.size();
	for(int i = 0; i < m; i++) sum += v[i].first;
	int best = sum;
	for(int i = 0; i < m; i++){
		int cur_sum = sum - v[i].first + v[i].second;
		best = max(best, cur_sum);
	}
	return best;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	string s;
	int k, a;
	cin >> k >> n;
	for(int i = 0; i < k; i++){
		cin >> s >> a;
		int ch = hsh(s);
		cnth[ch].push_back(a);
		revh[ch] = rev_hash(s);
	}
	int ans = 0;
	for(auto &p : revh){
		int first_hash = p.first;
		int second_hash = p.second;
		if(first_hash >= second_hash) continue;
		vector<int> &v1 = cnth[first_hash];
		vector<int> &v2 = cnth[second_hash];
		sort(v1.begin(), v1.end(), greater<int>());
		sort(v2.begin(), v2.end(), greater<int>());
		for(int i = 0; i < v1.size() && i < v2.size(); i++){
			if(v1[i] + v2[i] > 0) ans += v1[i] + v2[i];
		}
	}
	vector<pair<int, int>> sol;
	for(auto &p : revh){
		int first_hash = p.first;
		int second_hash = p.second;
		if(first_hash != second_hash) continue;
		vector<int> &v = cnth[first_hash];
		sort(v.begin(), v.end(), greater<int>());
		int sol_even = 0;
		for(int i = 0; i + 1 < v.size(); i += 2){
			if(v[i] + v[i + 1] > 0){
				sol_even += v[i] + v[i + 1];
			} else break;
		}
		int sol_odd = 0;
		if(v[0] > 0){
			sol_odd += v[0];
			for(int i = 1; i < v.size(); i += 2){
				if(v[i] + v[i + 1] > 0){
					sol_odd += v[i] + v[i + 1];
				} else break;
			}
		}
		sol.push_back({sol_even, sol_odd});
	}
	ans += solve(sol);
	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int HB = 359, HM = 1'000'000'033;
int n;
int add(int a, int b){
	return (a + b) % HM;
}
int mul(int a, int b){
	return (long long) a * b % HM;
}
int hsh(string s){
	int ans = 0;
	for(int i = 0; i < n; i++){
		ans = add(mul(HB, ans), s[i]);
	}
	return ans;
}
int rev_hash(string s){
	reverse(s.begin(), s.end());
	return hsh(s);
}
map<int, int> revh;
map<int, vector<int>> cnth;
int solve(vector<pair<int, int>> v){
	int sum = 0;
	int m = v.size();
	for(int i = 0; i < m; i++) sum += v[i].first;
	int best = sum;
	for(int i = 0; i < m; i++){
		int cur_sum = sum - v[i].first + v[i].second;
		best = max(best, cur_sum);
	}
	return best;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	string s;
	int k, a;
	cin >> k >> n;
	for(int i = 0; i < k; i++){
		cin >> s >> a;
		int ch = hsh(s);
		cnth[ch].push_back(a);
		revh[ch] = rev_hash(s);
	}
	int ans = 0;
	for(auto &p : revh){
		int first_hash = p.first;
		int second_hash = p.second;
		if(first_hash >= second_hash) continue;
		vector<int> &v1 = cnth[first_hash];
		vector<int> &v2 = cnth[second_hash];
		sort(v1.begin(), v1.end(), greater<int>());
		sort(v2.begin(), v2.end(), greater<int>());
		for(int i = 0; i < v1.size() && i < v2.size(); i++){
			if(v1[i] + v2[i] > 0) ans += v1[i] + v2[i];
		}
	}
	vector<pair<int, int>> sol;
	for(auto &p : revh){
		int first_hash = p.first;
		int second_hash = p.second;
		if(first_hash != second_hash) continue;
		vector<int> &v = cnth[first_hash];
		sort(v.begin(), v.end(), greater<int>());
		int sol_even = 0;
		for(int i = 0; i + 1 < v.size(); i += 2){
			if(v[i] + v[i + 1] > 0){
				sol_even += v[i] + v[i + 1];
			} else break;
		}
		int sol_odd = 0;
		if(v[0] > 0){
			sol_odd += v[0];
			for(int i = 1; i + 1 < v.size(); i += 2){
				if(v[i] + v[i + 1] > 0){
					sol_odd += v[i] + v[i + 1];
				} else break;
			}
		}
		sol.push_back({sol_even, sol_odd});
	}
	ans += solve(sol);
	printf("%d\n", ans);
	return 0;
}


/*
ID: dorijan1
TASK: tu napisi ime zadatka molim te molim te ali samo ako si na usaco training
LANG: C++11
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pii pair<int,int>

using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
const int MOD=1000000007;
const int MOD2=998244353;
vector<int> bases;
const ll LLINF=1ll<<60;
const char en='\n';

void yes() {cout<<"YES"<<en; exit(0);}
void no() {cout<<"NO"<<en; exit(0);}
template<class T>
void prVec(vector<T> w)
{
	cout<<w.size()<<endl;
	for (int i=0;i<int(w.size())-1;++i) cout<<w[i]<<' ';
	cout<<w[w.size()-1]<<endl;
}

ll raand()
{
	ll a=rand();
	a*=RAND_MAX;
	a+=rand();
    return a%(MOD-7);
}

string to_upper(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='a' && a[i]<='z') a[i]-='a'-'A';
	return a;
}

string to_lower(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='A' && a[i]<='Z') a[i]+='a'-'A';
	return a;
}

ll sti(string a)
{
	ll k=0;
	for (int i=0;i<(int)a.size();++i)
	{
		k*=10;
		k+=a[i]-'0';
	}
	return k;
}

string its(ll k)
{
	if (k==0) return "0";
	string a;
	while (k)
	{
		a.push_back((k%10)+'0');
		k/=10;
	}
	reverse(a.begin(),a.end());
	return a;
}

ll gcd(ll a,ll b)
{
	if (b==0) return a;
	return gcd(b,a%b);
}

template<class T,class K>
pair<T,K> mp(T a,K b)
{
	return make_pair(a,b);
}

ll mult(ll a,ll b)
{
	return (a*b)%MOD;
}

ll pot(ll n,ll k)
{
	if (k==0) return 1;
	ll a=pot(n,k/2);
	a=mult(a,a);
	if (k%2) return mult(a,n);
	else return a;
}

ll divide(ll a,ll b)
{
	return mult(a,pot(b,MOD-2));
}

ll sub(ll a,ll b)
{
	return (a-b+MOD)%MOD;
}

ll add(ll a,ll b)
{
	return (a+b)%MOD;
}

bool prime(ll a)
{
	if (a==1) return 0;
	for (int i=2;i<=round(sqrt(a));++i)
	{
		if (a%i==0) return 0;
	}
	return 1;
}

pair<int,int> has(string x)
{
	ll h1=0,h2=0;
	x=to_lower(x);
	for (char a: x)
	{
		h1*=bases[0];
		h1+=a-'a';
		h1%=MOD;
		h2*=bases[1];
		h2+=a-'a';
		h2%=MOD2;
	}
	return make_pair(h1,h2);
}

const int N=300010;
int n,k,re;
string h[N];
unordered_map<string,multiset<int> > m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
vector<pair<pair<int,int>,bool> > v;

int main()
{
	ios_base::sync_with_stdio(false);
	srand((long long)new char);
	for (int i=0;i<10;++i) bases.push_back(raand()+13893829);
	cin>>k>>n;
	for (int i=0;i<k;++i)
	{
		int a;
		cin>>h[i]>>a;
		m[h[i]].insert(a);
	}
	for (auto a: m)
	{
		string s=a.first;
		auto mu=a.second;
		reverse(s.begin(),s.end());
		if (s==a.first)
		{
			auto it=mu.rbegin();
			if ((*it)<=0) continue;
			if (mu.size()==1 || (*it)<=0)
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			auto miit=it;
			++miit;
			if (mu.size()==2 || (*miit)<=0)
			{
				v.push_back({{(*it),(*miit)},1});
				continue;
			}
			re+=(*it);
			++it;
			++it;
			bool flag=1;
			while (flag && it!=mu.rend() && (*it)>0)
			{
				re+=(*miit);
				++miit;
				++miit;
				if (miit==mu.rend()) break;
				else if ((*miit)<=0) break;
				re+=(*it);
				++it;
				++it;
			}
			if (miit==mu.rend())
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			if ((*miit)<=0)
			{
				v.push_back({{(*it),(*miit)},1});
				continue;
			}
			if (it==mu.rend())
			{
				v.push_back({{(*miit),-(*miit)},1});
				continue;
			}
			if ((*it)<=0)
			{
				v.push_back({{(*miit),(*it)},1});
				continue;
			}
		}
		else
		{
			auto su=m[s];
			m.erase(s);
			auto it=mu.rbegin(),bi=su.rbegin();
			while (it!=mu.rend() && bi!=su.rend() && ((*it)>0 || (*bi)>0))
			{
				if ((*it)>0 && (*bi)>0)
				{
					re+=(*it);
					re+=(*bi);
					++it;
					++bi;
					continue;
				}
				v.push_back({mp(max(*it,*bi),min(*it,*bi)),0});
				++it;
				++bi;
			}
			/*if (it!=mu.rend() && bi==su.rend())
			{
				v.push_back({*it,-(*it)});
				continue;
			}
			if (it==mu.rend() && bi!=su.rend())
			{
				v.push_back({*bi,-(*bi)});
			}*/
		}
	}
	int mi=0;
	//cout<<re<<endl;
	for (auto a: v)
	{
		re+=max(0,a.x.first+a.x.second);
		if (a.y) mi=min(mi,max(a.x.second,-a.x.x));
	}
	cout<<re-mi;
}


/*
ID: dorijan1
TASK: tu napisi ime zadatka molim te molim te ali samo ako si na usaco training
LANG: C++11
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pii pair<int,int>

using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
const int MOD=1000000007;
const int MOD2=998244353;
vector<int> bases;
const ll LLINF=1ll<<60;
const char en='\n';

void yes() {cout<<"YES"<<en; exit(0);}
void no() {cout<<"NO"<<en; exit(0);}
template<class T>
void prVec(vector<T> w)
{
	cout<<w.size()<<endl;
	for (int i=0;i<int(w.size())-1;++i) cout<<w[i]<<' ';
	cout<<w[w.size()-1]<<endl;
}

ll raand()
{
	ll a=rand();
	a*=RAND_MAX;
	a+=rand();
    return a%(MOD-7);
}

string to_upper(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='a' && a[i]<='z') a[i]-='a'-'A';
	return a;
}

string to_lower(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='A' && a[i]<='Z') a[i]+='a'-'A';
	return a;
}

ll sti(string a)
{
	ll k=0;
	for (int i=0;i<(int)a.size();++i)
	{
		k*=10;
		k+=a[i]-'0';
	}
	return k;
}

string its(ll k)
{
	if (k==0) return "0";
	string a;
	while (k)
	{
		a.push_back((k%10)+'0');
		k/=10;
	}
	reverse(a.begin(),a.end());
	return a;
}

ll gcd(ll a,ll b)
{
	if (b==0) return a;
	return gcd(b,a%b);
}

template<class T,class K>
pair<T,K> mp(T a,K b)
{
	return make_pair(a,b);
}

ll mult(ll a,ll b)
{
	return (a*b)%MOD;
}

ll pot(ll n,ll k)
{
	if (k==0) return 1;
	ll a=pot(n,k/2);
	a=mult(a,a);
	if (k%2) return mult(a,n);
	else return a;
}

ll divide(ll a,ll b)
{
	return mult(a,pot(b,MOD-2));
}

ll sub(ll a,ll b)
{
	return (a-b+MOD)%MOD;
}

ll add(ll a,ll b)
{
	return (a+b)%MOD;
}

bool prime(ll a)
{
	if (a==1) return 0;
	for (int i=2;i<=round(sqrt(a));++i)
	{
		if (a%i==0) return 0;
	}
	return 1;
}

pair<int,int> has(string x)
{
	ll h1=0,h2=0;
	x=to_lower(x);
	for (char a: x)
	{
		h1*=bases[0];
		h1+=a-'a';
		h1%=MOD;
		h2*=bases[1];
		h2+=a-'a';
		h2%=MOD2;
	}
	return make_pair(h1,h2);
}

const int N=300010;
int n,k,re;
string h[N];
unordered_map<string,multiset<int> > m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
vector<pair<int,int> > v;

int main()
{
	ios_base::sync_with_stdio(false);
	srand((long long)new char);
	for (int i=0;i<10;++i) bases.push_back(raand()+13893829);
	cin>>k>>n;
	for (int i=0;i<k;++i)
	{
		int a;
		cin>>h[i]>>a;
		m[h[i]].insert(a);
	}
	for (auto a: m)
	{
		string s=a.first;
		auto mu=a.second;
		reverse(s.begin(),s.end());
		if (s==a.first)
		{
			auto it=mu.rbegin();
			if ((*it)<=0) continue;
			if (mu.size()==1 || (*it)<=0)
			{
				v.push_back({(*it),-(*it)});
				continue;
			}
			auto miit=it;
			++miit;
			if (mu.size()==2 || (*miit)<=0)
			{
				v.push_back({(*it),(*miit)});
				continue;
			}
			re+=(*it);
			++it;
			++it;
			bool flag=1;
			while (flag && it!=mu.rend() && (*it)>0)
			{
				re+=(*miit);
				++miit;
				++miit;
				if (miit==mu.rend()) break;
				else if ((*miit)<=0) break;
				re+=(*it);
				++it;
				++it;
			}
			if (miit==mu.rend())
			{
				v.push_back({(*it),-(*it)});
				continue;
			}
			if ((*miit)<=0)
			{
				v.push_back({(*it),(*miit)});
				continue;
			}
			if (it==mu.rend())
			{
				v.push_back({(*miit),-(*miit)});
				continue;
			}
			if ((*it)<=0)
			{
				v.push_back({(*miit),(*it)});
				continue;
			}
		}
		else
		{
			auto su=m[s];
			m.erase(s);
			auto it=mu.rbegin(),bi=su.rbegin();
			while (it!=mu.rend() && bi!=su.rend() && ((*it)>0 || (*bi)>0))
			{
				if ((*it)>0 && (*bi)>0)
				{
					re+=(*it);
					re+=(*bi);
					++it;
					++bi;
					continue;
				}
				v.push_back(mp(max(*it,*bi),min(*it,*bi)));
				++it;
				++bi;
			}
			/*if (it!=mu.rend() && bi==su.rend())
			{
				v.push_back({*it,-(*it)});
				continue;
			}
			if (it==mu.rend() && bi!=su.rend())
			{
				v.push_back({*bi,-(*bi)});
			}*/
		}
	}
	int mi=0;
	for (auto a: v)
	{
		re+=max(0,a.first+a.second);
		mi=min(mi,a.second);
	}
	cout<<re-mi;
}


/*
ID: dorijan1
TASK: tu napisi ime zadatka molim te molim te ali samo ako si na usaco training
LANG: C++11
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pii pair<int,int>

using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
const int MOD=1000000007;
const int MOD2=998244353;
vector<int> bases;
const ll LLINF=1ll<<60;
const char en='\n';

void yes() {cout<<"YES"<<en; exit(0);}
void no() {cout<<"NO"<<en; exit(0);}
template<class T>
void prVec(vector<T> w)
{
	cout<<w.size()<<endl;
	for (int i=0;i<int(w.size())-1;++i) cout<<w[i]<<' ';
	cout<<w[w.size()-1]<<endl;
}

ll raand()
{
	ll a=rand();
	a*=RAND_MAX;
	a+=rand();
    return a%(MOD-7);
}

string to_upper(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='a' && a[i]<='z') a[i]-='a'-'A';
	return a;
}

string to_lower(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='A' && a[i]<='Z') a[i]+='a'-'A';
	return a;
}

ll sti(string a)
{
	ll k=0;
	for (int i=0;i<(int)a.size();++i)
	{
		k*=10;
		k+=a[i]-'0';
	}
	return k;
}

string its(ll k)
{
	if (k==0) return "0";
	string a;
	while (k)
	{
		a.push_back((k%10)+'0');
		k/=10;
	}
	reverse(a.begin(),a.end());
	return a;
}

ll gcd(ll a,ll b)
{
	if (b==0) return a;
	return gcd(b,a%b);
}

template<class T,class K>
pair<T,K> mp(T a,K b)
{
	return make_pair(a,b);
}

ll mult(ll a,ll b)
{
	return (a*b)%MOD;
}

ll pot(ll n,ll k)
{
	if (k==0) return 1;
	ll a=pot(n,k/2);
	a=mult(a,a);
	if (k%2) return mult(a,n);
	else return a;
}

ll divide(ll a,ll b)
{
	return mult(a,pot(b,MOD-2));
}

ll sub(ll a,ll b)
{
	return (a-b+MOD)%MOD;
}

ll add(ll a,ll b)
{
	return (a+b)%MOD;
}

bool prime(ll a)
{
	if (a==1) return 0;
	for (int i=2;i<=round(sqrt(a));++i)
	{
		if (a%i==0) return 0;
	}
	return 1;
}

pair<int,int> has(string x)
{
	ll h1=0,h2=0;
	x=to_lower(x);
	for (char a: x)
	{
		h1*=bases[0];
		h1+=a-'a';
		h1%=MOD;
		h2*=bases[1];
		h2+=a-'a';
		h2%=MOD2;
	}
	return make_pair(h1,h2);
}

const int N=300010;
int n,k,re;
string h[N];
map<string,multiset<int> > m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
vector<pair<pair<int,int>,bool> > v;

int main()
{
	ios_base::sync_with_stdio(false);
	srand((long long)new char);
	for (int i=0;i<10;++i) bases.push_back(raand()+13893829);
	cin>>k>>n;
	for (int i=0;i<k;++i)
	{
		int a;
		cin>>h[i]>>a;
		m[h[i]].insert(a);
	}
	for (auto a: m)
	{
		string s=a.first;
		auto mu=a.second;
		reverse(s.begin(),s.end());
		if (s==a.first)
		{
			auto it=mu.rbegin();
			if ((*it)<=0) continue;
			if (mu.size()==1)
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			auto miit=it;
			++miit;
			v.push_back({{(*it),(*miit)},1});
			//cout<<a.first<<endl;
			while (miit!=mu.rend() && (*it)>0)
			{
				++miit;
				++miit;
				++it;
				++it;
				if (it==mu.rend() || miit==mu.rend()) break;
				v.push_back({{(*it),(*miit)},1});
			}
			if (it==mu.rend())
			{
				continue;
			}
			if ((*it)<=0)
			{
				continue;
			}
			if (miit==mu.rend())
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			if ((*miit)<=0)
			{
				v.push_back({{(*it),(*miit)},1});
				continue;
			}
		}
		else
		{
			auto su=m[s];
			m.erase(s);
			auto it=mu.rbegin(),bi=su.rbegin();
			while (it!=mu.rend() && bi!=su.rend() && ((*it)>0 || (*bi)>0))
			{
				if ((*it)>0 && (*bi)>0)
				{
					re+=(*it);
					re+=(*bi);
					++it;
					++bi;
					continue;
				}
				v.push_back({mp(max(*it,*bi),min(*it,*bi)),0});
				++it;
				++bi;
			}
			/*if (it!=mu.rend() && bi==su.rend())
			{
				v.push_back({*it,-(*it)});
				continue;
			}
			if (it==mu.rend() && bi!=su.rend())
			{
				v.push_back({*bi,-(*bi)});
			}*/
		}
	}
	int mi=0;
	//cout<<re<<endl;
	for (auto a: v)
	{
		re+=max(0,a.x.first+a.x.second);
		if (a.y) mi=min(mi,max(a.x.second,-a.x.x));
		//cout<<a.x.x<<' '<<a.x.y<<endl;
	}
	cout<<re-mi;
}


/*
ID: dorijan1
TASK: tu napisi ime zadatka molim te molim te ali samo ako si na usaco training
LANG: C++11
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pii pair<int,int>

using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
const int MOD=1000000007;
const int MOD2=998244353;
vector<int> bases;
const ll LLINF=1ll<<60;
const char en='\n';

void yes() {cout<<"YES"<<en; exit(0);}
void no() {cout<<"NO"<<en; exit(0);}
template<class T>
void prVec(vector<T> w)
{
	cout<<w.size()<<endl;
	for (int i=0;i<int(w.size())-1;++i) cout<<w[i]<<' ';
	cout<<w[w.size()-1]<<endl;
}

ll raand()
{
	ll a=rand();
	a*=RAND_MAX;
	a+=rand();
    return a%(MOD-7);
}

string to_upper(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='a' && a[i]<='z') a[i]-='a'-'A';
	return a;
}

string to_lower(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='A' && a[i]<='Z') a[i]+='a'-'A';
	return a;
}

ll sti(string a)
{
	ll k=0;
	for (int i=0;i<(int)a.size();++i)
	{
		k*=10;
		k+=a[i]-'0';
	}
	return k;
}

string its(ll k)
{
	if (k==0) return "0";
	string a;
	while (k)
	{
		a.push_back((k%10)+'0');
		k/=10;
	}
	reverse(a.begin(),a.end());
	return a;
}

ll gcd(ll a,ll b)
{
	if (b==0) return a;
	return gcd(b,a%b);
}

template<class T,class K>
pair<T,K> mp(T a,K b)
{
	return make_pair(a,b);
}

ll mult(ll a,ll b)
{
	return (a*b)%MOD;
}

ll pot(ll n,ll k)
{
	if (k==0) return 1;
	ll a=pot(n,k/2);
	a=mult(a,a);
	if (k%2) return mult(a,n);
	else return a;
}

ll divide(ll a,ll b)
{
	return mult(a,pot(b,MOD-2));
}

ll sub(ll a,ll b)
{
	return (a-b+MOD)%MOD;
}

ll add(ll a,ll b)
{
	return (a+b)%MOD;
}

bool prime(ll a)
{
	if (a==1) return 0;
	for (int i=2;i<=round(sqrt(a));++i)
	{
		if (a%i==0) return 0;
	}
	return 1;
}

pair<int,int> has(string x)
{
	ll h1=0,h2=0;
	x=to_lower(x);
	for (char a: x)
	{
		h1*=bases[0];
		h1+=a-'a';
		h1%=MOD;
		h2*=bases[1];
		h2+=a-'a';
		h2%=MOD2;
	}
	return make_pair(h1,h2);
}

const int N=300010;
int n,k,re;
string h[N];
unordered_map<string,multiset<int> > m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
vector<pair<pair<int,int>,bool> > v;

int main()
{
	ios_base::sync_with_stdio(false);
	srand((long long)new char);
	for (int i=0;i<10;++i) bases.push_back(raand()+13893829);
	cin>>k>>n;
	for (int i=0;i<k;++i)
	{
		int a;
		cin>>h[i]>>a;
		m[h[i]].insert(a);
	}
	for (auto a: m)
	{
		string s=a.first;
		auto mu=a.second;
		reverse(s.begin(),s.end());
		if (s==a.first)
		{
			auto it=mu.rbegin();
			if ((*it)<=0) continue;
			if (mu.size()==1)
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			auto miit=it;
			++miit;
			v.push_back({{(*it),(*miit)},1});
			//cout<<a.first<<endl;
			while (miit!=mu.rend() && (*it)>0)
			{
				++miit;
				++miit;
				++it;
				++it;
				if (it==mu.rend() || miit==mu.rend()) break;
				v.push_back({{(*it),(*miit)},1});
			}
			if (it==mu.rend())
			{
				continue;
			}
			if ((*it)<=0)
			{
				continue;
			}
			if (miit==mu.rend())
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			if ((*miit)<=0)
			{
				v.push_back({{(*it),(*miit)},1});
				continue;
			}
		}
		else
		{
			auto su=m[s];
			m.erase(s);
			auto it=mu.rbegin(),bi=su.rbegin();
			while (it!=mu.rend() && bi!=su.rend() && ((*it)>0 || (*bi)>0))
			{
				if ((*it)>0 && (*bi)>0)
				{
					re+=(*it);
					re+=(*bi);
					++it;
					++bi;
					continue;
				}
				v.push_back({mp(max(*it,*bi),min(*it,*bi)),0});
				++it;
				++bi;
			}
			/*if (it!=mu.rend() && bi==su.rend())
			{
				v.push_back({*it,-(*it)});
				continue;
			}
			if (it==mu.rend() && bi!=su.rend())
			{
				v.push_back({*bi,-(*bi)});
			}*/
		}
	}
	int mi=0;
	//cout<<re<<endl;
	for (auto a: v)
	{
		re+=max(0,a.x.first+a.x.second);
		if (a.y) mi=min(mi,max(a.x.second,-a.x.x));
		//cout<<a.x.x<<' '<<a.x.y<<endl;
	}
	cout<<re-mi;
}


/*
ID: dorijan1
TASK: tu napisi ime zadatka molim te molim te ali samo ako si na usaco training
LANG: C++11
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pii pair<int,int>

using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
const int MOD=1000000007;
const int MOD2=998244353;
vector<int> bases;
const ll LLINF=1ll<<60;
const char en='\n';

void yes() {cout<<"YES"<<en; exit(0);}
void no() {cout<<"NO"<<en; exit(0);}
template<class T>
void prVec(vector<T> w)
{
	cout<<w.size()<<endl;
	for (int i=0;i<int(w.size())-1;++i) cout<<w[i]<<' ';
	cout<<w[w.size()-1]<<endl;
}

ll raand()
{
	ll a=rand();
	a*=RAND_MAX;
	a+=rand();
    return a%(MOD-7);
}

string to_upper(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='a' && a[i]<='z') a[i]-='a'-'A';
	return a;
}

string to_lower(string a)
{
	for (int i=0;i<(int)a.size();++i) if (a[i]>='A' && a[i]<='Z') a[i]+='a'-'A';
	return a;
}

ll sti(string a)
{
	ll k=0;
	for (int i=0;i<(int)a.size();++i)
	{
		k*=10;
		k+=a[i]-'0';
	}
	return k;
}

string its(ll k)
{
	if (k==0) return "0";
	string a;
	while (k)
	{
		a.push_back((k%10)+'0');
		k/=10;
	}
	reverse(a.begin(),a.end());
	return a;
}

ll gcd(ll a,ll b)
{
	if (b==0) return a;
	return gcd(b,a%b);
}

template<class T,class K>
pair<T,K> mp(T a,K b)
{
	return make_pair(a,b);
}

ll mult(ll a,ll b)
{
	return (a*b)%MOD;
}

ll pot(ll n,ll k)
{
	if (k==0) return 1;
	ll a=pot(n,k/2);
	a=mult(a,a);
	if (k%2) return mult(a,n);
	else return a;
}

ll divide(ll a,ll b)
{
	return mult(a,pot(b,MOD-2));
}

ll sub(ll a,ll b)
{
	return (a-b+MOD)%MOD;
}

ll add(ll a,ll b)
{
	return (a+b)%MOD;
}

bool prime(ll a)
{
	if (a==1) return 0;
	for (int i=2;i<=round(sqrt(a));++i)
	{
		if (a%i==0) return 0;
	}
	return 1;
}

pair<int,int> has(string x)
{
	ll h1=0,h2=0;
	x=to_lower(x);
	for (char a: x)
	{
		h1*=bases[0];
		h1+=a-'a';
		h1%=MOD;
		h2*=bases[1];
		h2+=a-'a';
		h2%=MOD2;
	}
	return make_pair(h1,h2);
}

const int N=300010;
int n,k,re;
string h[N];
unordered_map<string,multiset<int> > m;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
vector<pair<pair<int,int>,bool> > v;

int main()
{
	ios_base::sync_with_stdio(false);
	srand((long long)new char);
	for (int i=0;i<10;++i) bases.push_back(raand()+13893829);
	cin>>k>>n;
	for (int i=0;i<k;++i)
	{
		int a;
		cin>>h[i]>>a;
		m[h[i]].insert(a);
	}
	for (auto a: m)
	{
		string s=a.first;
		auto mu=a.second;
		reverse(s.begin(),s.end());
		if (s==a.first)
		{
			auto it=mu.rbegin();
			if ((*it)<=0) continue;
			if (mu.size()==1 || (*it)<=0)
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			auto miit=it;
			++miit;
			if (mu.size()==2 || (*miit)<=0)
			{
				v.push_back({{(*it),(*miit)},1});
				continue;
			}
			re+=(*it);
			++it;
			++it;
			bool flag=1;
			while (flag && it!=mu.rend() && (*it)>0)
			{
				re+=(*miit);
				++miit;
				++miit;
				if (miit==mu.rend()) break;
				else if ((*miit)<=0) break;
				re+=(*it);
				++it;
				++it;
			}
			if (miit==mu.rend())
			{
				v.push_back({{(*it),-(*it)},1});
				continue;
			}
			if ((*miit)<=0)
			{
				v.push_back({{(*it),(*miit)},1});
				continue;
			}
			if (it==mu.rend())
			{
				v.push_back({{(*miit),-(*miit)},1});
				continue;
			}
			if ((*it)<=0)
			{
				v.push_back({{(*miit),(*it)},1});
				continue;
			}
		}
		else
		{
			auto su=m[s];
			m.erase(s);
			auto it=mu.rbegin(),bi=su.rbegin();
			while (it!=mu.rend() && bi!=su.rend() && ((*it)>0 || (*bi)>0))
			{
				if ((*it)>0 && (*bi)>0)
				{
					re+=(*it);
					re+=(*bi);
					++it;
					++bi;
					continue;
				}
				v.push_back({mp(max(*it,*bi),min(*it,*bi)),0});
				++it;
				++bi;
			}
			/*if (it!=mu.rend() && bi==su.rend())
			{
				v.push_back({*it,-(*it)});
				continue;
			}
			if (it==mu.rend() && bi!=su.rend())
			{
				v.push_back({*bi,-(*bi)});
			}*/
		}
	}
	int mi=0;
	for (auto a: v)
	{
		re+=max(0,a.x.first+a.x.second);
		if (a.y) mi=min(mi,a.x.second);
	}
	cout<<re-mi;
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
typedef long long ll;
typedef double db;
const int N = 1e5+100;
const int M = 1e5+100;
const db EPS = 1e-9;
using namespace std;

int len,n,tot,vis[N];
map<string,int> mp;
ll ans,maxn;
struct Node{
	string s;
	priority_queue<int> q;
}t[N];

int main()
{
	__;
	cin >> n >> len;
	rep(i,1,n){
		string xx; cin >> xx;
		int hp; cin >> hp;
		int pos;
		if(mp.find(xx) == mp.end()){
			pos = ++tot, mp[xx] = tot;
			t[pos].s = xx;
			t[pos].q.push(hp);
		}
		else{
			pos = mp[xx];
			t[pos].q.push(hp);
		}
	}
	rep(i,1,tot){
		if(vis[i]) continue;
		string yy = t[i].s, xx;
		xx = yy; reverse(yy.begin(),yy.end());
		int pos = mp[yy];
		if(xx == yy){
			while(t[i].q.size() >= 2){
				ll vx = t[i].q.top(); t[i].q.pop();
				ll vy = t[i].q.top(); t[i].q.pop();
				if(vx+vy < 0){
					maxn = max(vx,maxn);
				}
				else{
					ans += vx+vy;
					if(vy < 0) maxn = max(maxn,-vy);
				}
			}
			if(t[i].q.size() >= 1){
				ll vx = t[i].q.top(); t[i].q.pop();
				maxn = max(maxn,vx);
			}
		}
		else if(pos != 0){
			while(t[i].q.size() && t[pos].q.size()){
				ll vx = t[i].q.top(); t[i].q.pop();
				ll vy = t[pos].q.top(); t[pos].q.pop();
				if(vx+vy < 0) break;
				else ans += vx+vy;
			}
		}
	}
	cout << ans+maxn << endl;
	return 0;
}

/*
multiset删除元素：
	· erase(val) —— 删除所有val
	· erase(set.find(val)) —— 删除单个val
*/


#include<bits/stdc++.h>
#define ll long long
#define INF 1e14
#define pb push_back
#define sec second
#define fir first
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lele(a) int a;cin>>a;
#define ios ios_base::sync_with_stdio(false); cin.tie(NULL);
using namespace std;
int main() {
	lele(k) lele(n)
	map<string, vector<int> > mappa;
	rep(i,0,k-1)
	{
	    string s;int val;
	    cin>>s>>val;
	    mappa[s].pb(val);
	}
	ll ans=0;
	int mx = 0;
	for(auto it:mappa)
	{
	    string temp = it.first,rtemp = it.first;
	    reverse(rtemp.begin(),rtemp.end());
	    if(rtemp < temp )continue;
	    if(rtemp == temp)
	    {
	        sort(mappa[temp].begin(),mappa[temp].end(),greater<int> ());
	        int i;
	        for(i=0;i+1<mappa[temp].size();i += 2)
	        {
	            if(mappa[temp][i] + mappa[temp][i+1] >= 0)
	            {
	                ans += mappa[temp][i] + mappa[temp][i+1];
	                mx = max(mx,-mappa[temp][i+1]);
	            }
	            else break;
	        }
	        if(i < mappa[temp].size()) mx = max(mx,mappa[temp][i]);
	       // cout<<"lol"<<ans<<endl;
	    }
	    else
	    {
	       // cout<<min(mappa[temp].size(),mappa[rtemp].size())<<endl;
	       sort(mappa[temp].begin(),mappa[temp].end(),greater<int> ());
	       sort(mappa[rtemp].begin(),mappa[rtemp].end(),greater<int> ());
	        for(int i=0;i < min(mappa[temp].size(),mappa[rtemp].size());i++)
	        {
	           // cout<<mappa[temp][i] + mappa[rtemp][i];
	            if(mappa[temp][i] + mappa[rtemp][i] >= 0)
	            {
	                ans += mappa[temp][i] + mappa[rtemp][i];
	            }
	            else
	            {
	                break;
	            }
	        }
	       // cout<<"llo"<<ans<<endl;
	    }

	}
	ans = max(ans,ans+mx);
    cout<<ans<<endl;
}


#include<bits/stdc++.h>
#define ll long long
#define INF 1e14
#define pb push_back
#define sec second
#define fir first
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lele(a) int a;cin>>a;
#define ios ios_base::sync_with_stdio(false); cin.tie(NULL);
using namespace std;
int main() {
	lele(k) lele(n)
	map<string, vector<int> > mappa;
	rep(i,0,k-1)
	{
	    string s;int val;
	    cin>>s>>val;
	    mappa[s].pb(val);
	}
	ll ans=0;
	int mx = 0;
	for(auto it:mappa)
	{
	    string temp = it.first,rtemp = it.first;
	    reverse(rtemp.begin(),rtemp.end());
	    if(rtemp < temp )continue;
	    sort(mappa[temp].begin(),mappa[temp].end(),greater<int> ());
	    sort(mappa[rtemp].begin(),mappa[rtemp].end(),greater<int> ());
	    if(rtemp == temp)
	    {
	        for(int i=0;i<mappa[temp].size();i += 2)
	        {
	            if(mappa[temp][i] + mappa[temp][i+1] >= 0)
	            {
	                ans += mappa[temp][i] + mappa[temp][i+1];
	            }
	            else if(mappa[temp][i] < 0 &&  mappa[temp][i+1] < 0)break;
	            else if(mappa[temp][i] >=0 && mappa[temp][i+1] < 0)
	            {
	                mx = max(mx,-mappa[temp][i+1]);
	            }
	        }
	    }
	    else
	    {
	       // cout<<min(mappa[temp].size(),mappa[rtemp].size())<<endl;
	        for(int i=0;i < min(mappa[temp].size(),mappa[rtemp].size());i++)
	        {
	            if(mappa[temp][i] + mappa[rtemp][i] >= 0)
	            {
	                ans += mappa[temp][i] + mappa[rtemp][i];
	            }
	            else
	            {
	                break;
	            }
	        }
	       // cout<<ans<<endl;
	    }

	}
	ans = max(ans,ans+mx);
    cout<<ans<<endl;
}


#include<bits/stdc++.h>
#define ll long long
#define INF 1e14
#define pb push_back
#define sec second
#define fir first
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lele(a) int a;cin>>a;
#define ios ios_base::sync_with_stdio(false); cin.tie(NULL);
using namespace std;
int main() {
	lele(k) lele(n)
	map<string, vector<int> > mappa;
	rep(i,0,k-1)
	{
	    string s;int val;
	    cin>>s>>val;
	    mappa[s].pb(val);
	}
	ll ans=0;
	int mx = 0;
	for(auto it:mappa)
	{
	    string temp = it.first,rtemp = it.first;
	    reverse(rtemp.begin(),rtemp.end());
	    if(rtemp < temp )continue;
	    sort(mappa[temp].begin(),mappa[temp].end(),greater<int> ());
	    sort(mappa[rtemp].begin(),mappa[rtemp].end(),greater<int> ());
	    if(rtemp == temp)
	    {
	        int i;
	        for(i=0;i+1<mappa[temp].size();i += 2)
	        {
	            if(mappa[temp][i] + mappa[temp][i+1] >= 0)
	            {
	                ans += mappa[temp][i] + mappa[temp][i+1];
	                mx = max(mx,-mappa[temp][i+1]);
	            }
	            else break;
	        }
	        if(i<mappa[temp].size()) mx = max(mx,-mappa[temp][i]);
	    }
	    else
	    {
	       // cout<<min(mappa[temp].size(),mappa[rtemp].size())<<endl;
	        for(int i=0;i < min(mappa[temp].size(),mappa[rtemp].size());i++)
	        {
	            if(mappa[temp][i] + mappa[rtemp][i] >= 0)
	            {
	                ans += mappa[temp][i] + mappa[rtemp][i];
	            }
	            else
	            {
	                break;
	            }
	        }
	       // cout<<ans<<endl;
	    }

	}
	ans = max(ans,ans+mx);
    cout<<ans<<endl;
}


#include<bits/stdc++.h>
///...................................*****.................................................///
/// Author : Tanvir Ahmed ///
/// Department of Computer Science ///
/// & Engineering ///
/// Comilla University , Bangladesh. ///
///...................................*****.................................................///

/*....................................Values................................................*/
#define inf 1<<30
#define p5 100007
#define p6 1000007
#define PI acos(-1)
#define M 1000000007

/*....................................Functions.............................................*/
#define sqr(x) x*x
#define sc scanf
#define pf printf
#define scin(x) sc("%d",&(x))
#define scin2(x,y) sc("d",&(x),&(y))
#define scin3(x,y,z) sc("d%d",&(x),&(y),&(z))
#define scln(x) sc("%lld",&(x))
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define all(v) v.begin(), v.end()
#define ok cout << "ok" << endl
#define mem(x,y) memset(x,y,sizeof(x))
#define READ(f) freopen(f, "r", stdin)
#define WRITE(f) freopen(f, "w", stdout)

/*...................................Data_Types............................................*/
#define lli long long int
#define ull unsigned long long int
#define pii pair < int, int>
#define pll pair < ll, ll>
#define veci vector<int>
#define vecl vector<long long int>
#define vecp vector< pair<int,int> >
#define mapstrint map< string , int >
#define mapstrstr map< string , string >
#define mapint map< int, int >
#define uset unordered_set
#define umap unordered_map
#define pq priority_queue

#define pb push_back
#define mp make_pair
#define ss stringstream

/*.....................................Loops...............................................*/
#define rep( i , a , b ) for( i=a ; i<b ; i++)
#define rev( i , a , b ) for( i=a ; i>=b ; i--)
#define repx( i ,a,b, x) for( i=a ; i<b ; i+=x)

#define FastRead ios_base::sync_with_stdio(0);cin.tie(0)

//int month[]={31,28,31,30,31,30,31,31,30,31,30,31};
//long power(long int x, long int y){ int temp; if( y == 0) return 1; temp = power(x, y/2); if (y%2 == 0) return temp*temp; else return x*temp*temp; }
/*lli gcd(lli x,lli y)
{
if(x==0) return y;
return gcd(y%x,x);
}*/
/*
int dx[5] = {1, -1, 0, 0 };
int dy[5] = {0, 0, 1, -1};
*/

using namespace std;

vector<lli> vec[100005];
map<string,string> ms;
map<string,lli> mi,com,vis,m;
///map<lli, lli> m;
set<string> st,st1;
set<string> :: iterator it;

lli power[500005], p = 31, mod=1000000009, h[500005],hrev[500005],a[100005];

lli val(void)
{
    power[0] = 1;
    for(int i=1; i<=100005; i++)
    {
        power[i] = (p * power[i-1]) % mod;
    }
}

lli has(string s)
{
    lli a,b,c,d;
    int len = s.size();
    lli valu = 0;
    for(int i=0; i<len; i++)
    {
        a=((s[i]-97+1) * power[i]);
        valu = valu + a;
    }
    return valu;
}

int main()
{
    val();
    int n,cnt=1,len;
    scin(n),scin(len);
    for(int i=0; i<n; i++)
    {
        string s,s1;
        cin>>s1>>a[i];
        s = s1;
        reverse(s1.begin(),s1.end());
        lli val1,val2;
        val1 = has(s);
        val2 = has(s1);
        if(val1 == val2)
        {
            st1.insert(s);
        }
        else
        {
            st.insert(s);
        }
        m[s] = 1;
        if(com[s] == 0)
        {
            com[s] = cnt++;
        }
        vec[com[s]].push_back(a[i]);
        ms[s] = s1;
        mi[s] = val1;
        mi[s1] = val2;
    }
    ///cout<<endl<<endl;
    for(it = st.begin(); it != st.end(); ++it)
    {
        string s2;
        s2 = *it;
        int v = com[s2];
        sort(vec[v].begin(),vec[v].end());
        reverse(vec[v].begin(),vec[v].end());
        /*cout<<s2<<" : ";
        int siz = vec[v].size();
        for(int i=0; i<siz; i++)
        {
            cout<<vec[v][i]<<" ";
        }
        cout<<endl;*/
    }
   /// cout<<endl<<endl;
    for(it = st1.begin(); it != st1.end(); ++it)
    {

        string s2;
        s2 = *it;
        int v = com[s2];
        sort(vec[v].begin(),vec[v].end());
        reverse(vec[v].begin(),vec[v].end());
        /*cout<<s2<<" : ";
        int siz = vec[v].size();
        for(int i=0; i<siz; i++)
        {
            cout<<vec[v][i]<<" ";
        }
        cout<<endl;*/
    }
    lli sum = 0;
    for(it = st.begin(); it != st.end(); ++it)
    {
        string s2,s3;
        s2 = *it;
        s3 = ms[s2];
        if(vis[s2] == 0)
        {
            if(m[s3] == 1)
            {
                int val3 = com[s2];
                int val4 = com[s3];
                int siz1 = vec[val3].size();
                int siz2 = vec[val4].size();
                int mn = min(siz1,siz2);
                for(int i=0; i<mn;i++)
                {
                    lli v1=vec[val3][i];
                    lli v2=vec[val4][i];
                    lli sum1 = v1+v2;
                    if(sum1>0)
                    {
                        sum = sum + sum1;
                    }
                    else
                        break;
                }
                vis[s2] = 1;
                vis[s3] = 1;
            }
            vis[s2] = 1;
        }
    }
    lli mx=-10000000000;
    for(it = st1.begin(); it != st1.end(); ++it)
    {
        string s4 = *it;
        int v4 = com[s4];
        int siz = vec[v4].size();
        for(int i=0; i<siz; i = i+2)
        {

            if(i==siz-1)
            {
                mx = max(mx,vec[v4][i]);
            }
            else
            {
                if((vec[v4][i]+vec[v4][i+1])>0)
                {
                    sum = sum + (vec[v4][i]+vec[v4][i+1]);

                    //cout<<sum<<endl;
                }
                else
                {
                    mx = max(mx,vec[v4][i]);
                    break;
                }
            }
        }
    }
    if(mx>0)
        sum+=mx;
    cout<<sum<<endl;
    return 0;
}


    #include<bits/stdc++.h>
    ///...................................*****.................................................///
    /// Author : Tanvir Ahmed ///
    /// Department of Computer Science ///
    /// & Engineering ///
    /// Comilla University , Bangladesh. ///
    ///...................................*****.................................................///

    /*....................................Values................................................*/
    #define inf 1<<30
    #define p5 100007
    #define p6 1000007
    #define PI acos(-1)
    #define M 1000000007

    /*....................................Functions.............................................*/
    #define sqr(x) x*x
    #define sc scanf
    #define pf printf
    #define scin(x) sc("%d",&(x))
    #define scin2(x,y) sc("d",&(x),&(y))
    #define scin3(x,y,z) sc("d%d",&(x),&(y),&(z))
    #define scln(x) sc("%lld",&(x))
    #define min3(a,b,c) min(a,min(b,c))
    #define max3(a,b,c) max(a,max(b,c))
    #define all(v) v.begin(), v.end()
    #define ok cout << "ok" << endl
    #define mem(x,y) memset(x,y,sizeof(x))
    #define READ(f) freopen(f, "r", stdin)
    #define WRITE(f) freopen(f, "w", stdout)

    /*...................................Data_Types............................................*/
    #define lli long long int
    #define ull unsigned long long int
    #define pii pair < int, int>
    #define pll pair < ll, ll>
    #define veci vector<int>
    #define vecl vector<long long int>
    #define vecp vector< pair<int,int> >
    #define mapstrint map< string , int >
    #define mapstrstr map< string , string >
    #define mapint map< int, int >
    #define uset unordered_set
    #define umap unordered_map
    #define pq priority_queue

    #define pb push_back
    #define mp make_pair
    #define ss stringstream

    /*.....................................Loops...............................................*/
    #define rep( i , a , b ) for( i=a ; i<b ; i++)
    #define rev( i , a , b ) for( i=a ; i>=b ; i--)
    #define repx( i ,a,b, x) for( i=a ; i<b ; i+=x)

    #define FastRead ios_base::sync_with_stdio(0);cin.tie(0)

    //int month[]={31,28,31,30,31,30,31,31,30,31,30,31};
    //long power(long int x, long int y){ int temp; if( y == 0) return 1; temp = power(x, y/2); if (y%2 == 0) return temp*temp; else return x*temp*temp; }
    /*lli gcd(lli x,lli y)
    {
    if(x==0) return y;
    return gcd(y%x,x);
    }*/
    /*
    int dx[5] = {1, -1, 0, 0 };
    int dy[5] = {0, 0, 1, -1};
    */

    using namespace std;

    vector<lli> vec[100005];
    map<string,string> ms;
    map<string,lli> mi,com,vis,m;
    ///map<lli, lli> m;
    set<string> st,st1;
    set<string> :: iterator it;

    lli power[500005], p = 31, mod=1000000009, h[500005],hrev[500005],a[100005];

    lli val(void)
    {
        power[0] = 1;
        for(int i=1; i<=100005; i++)
        {
            power[i] = (p * power[i-1]) % mod;
        }
    }

    lli has(string s)
    {
        lli a,b,c,d;
        int len = s.size();
        lli valu = 0;
        for(int i=0; i<len; i++)
        {
            a=((s[i]-97+1) * power[i]);
            valu = valu + a;
        }
        return valu;
    }

    int main()
    {
        val();
        int n,cnt=1,len;
        scin(n),scin(len);
        for(int i=0; i<n; i++)
        {
            string s,s1;
            cin>>s1>>a[i];
            s = s1;
            reverse(s1.begin(),s1.end());
            lli val1,val2;
            val1 = has(s);
            val2 = has(s1);
            if(val1 == val2)
            {
                st1.insert(s);
            }
            else
            {
                st.insert(s);
            }
            m[s] = 1;
            if(com[s] == 0)
            {
                com[s] = cnt++;
            }
            vec[com[s]].push_back(a[i]);
            ms[s] = s1;
            mi[s] = val1;
            mi[s1] = val2;
        }
        ///cout<<endl<<endl;
        for(it = st.begin(); it != st.end(); ++it)
        {
            string s2;
            s2 = *it;
            int v = com[s2];
            sort(vec[v].begin(),vec[v].end());
            reverse(vec[v].begin(),vec[v].end());
            /*cout<<s2<<" : ";
            int siz = vec[v].size();
            for(int i=0; i<siz; i++)
            {
                cout<<vec[v][i]<<" ";
            }
            cout<<endl;*/
        }
       /// cout<<endl<<endl;
        for(it = st1.begin(); it != st1.end(); ++it)
        {

            string s2;
            s2 = *it;
            int v = com[s2];
            sort(vec[v].begin(),vec[v].end());
            reverse(vec[v].begin(),vec[v].end());
            /*cout<<s2<<" : ";
            int siz = vec[v].size();
            for(int i=0; i<siz; i++)
            {
                cout<<vec[v][i]<<" ";
            }
            cout<<endl;*/
        }
        lli sum = 0;
        for(it = st.begin(); it != st.end(); ++it)
        {
            string s2,s3;
            s2 = *it;
            s3 = ms[s2];
            if(vis[s2] == 0)
            {
                if(m[s3] == 1)
                {
                    int val3 = com[s2];
                    int val4 = com[s3];
                    int siz1 = vec[val3].size();
                    int siz2 = vec[val4].size();
                    int mn = min(siz1,siz2);
                    for(int i=0; i<mn;i++)
                    {
                        lli v1=vec[val3][i];
                        lli v2=vec[val4][i];
                        lli sum1 = v1+v2;
                        if(sum1>0)
                        {
                            sum = sum + sum1;
                        }
                        else
                            break;
                    }
                    vis[s2] = 1;
                    vis[s3] = 1;
                }
                vis[s2] = 1;
            }
        }
        lli mx=0,mn=10000000000;
        for(it = st1.begin(); it != st1.end(); ++it)
        {
            string s4 = *it;
            int v4 = com[s4];
            int siz = vec[v4].size();
            for(int i=0; i<siz; i = i+2)
            {

                if(i==siz-1)
                {
                    mx = max(mx,vec[v4][i]);
                }
                else
                {
                    if((vec[v4][i]+vec[v4][i+1])>0)
                    {
                        sum = sum + (vec[v4][i]+vec[v4][i+1]);
                        if(vec[v4][i+1]<0)
                        {
                            mn=min(mn,vec[v4][i+1]);
                        }
                        //cout<<sum<<endl;
                    }
                    else
                    {
                        mx = max(mx,vec[v4][i]);
                        break;
                    }
                }
            }
        }
        lli res = max(sum+mx,sum-mn);
        if(mx>0)
            sum+=mx;
        cout<<res<<endl;
        return 0;
    }