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

#define nl printf("\n")
#define pb(x) push_back(x)

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define P(a) printf("%d",a)

#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)

#define PL(a) printf("%lld",a)
#define PLN(a) printf("%lld\n",a)
#define PLC(a) printf("%lld ",a)
#define SL(a) scanf("%lld",&a)
#define SL2(a,b) scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SL4(a,b,c,d) scanf("%lld%lld%lld%lld",&a,&b,&c,&d)

#define CLR(a) memset(a,0,sizeof(a))
#define SET(a) memset(a,-1,sizeof(a))
#define FOOL(a) memset(a,false,sizeof(a))
#define fr(i,a,n) for(i=a;i<=n;i++)
#define frv(i,v) for(i=0;i<(int)v.size();i++)
#define frs(i,v) for(i=0;i<(int)v.length();i++)
#define pi acos(-1.0)
#define po 400001
#define co 1000000
#define mod 786433
#define inf 10000000

using namespace std;
ll f[100001];
struct node
{
    ll a,b,c,d;
    node(){};
    node(ll aa,ll bb,ll cc,ll dd){a=aa,b=bb,c=cc,d=dd;}
};
struct cmp
{
    bool operator()(const node& x,const node& y)const
    {
        if(x.a!=y.a)return x.a<y.a;
        if(x.b!=y.b)return x.b<y.b;
        if(x.c!=y.c)return x.c>y.c;
        return x.d<y.d;
    }
};
ll ptr=-1;
int main()
{
    string ss;
    ll k,n,x,y,i,z,ans=0,sofar;
    set<node,cmp> s;
    f[0]=1;
    fr(i,1,100000)
        f[i]=(f[i-1]*31LL)%mod;
    SL2(k,n);
    while(k--)
    {
        cin>>ss;
        x=0,y=0;
        frs(i,ss)
        {
            x=(x+(ss[i]-'a')*f[i])%mod;
            y=(y+(ss[i]-'a')*f[n-1-i])%mod;
        }
        SL(z);
            s.insert(node(x,y,z,++ptr));
    }
    sofar=0;
    while(1)
    {
        if(s.empty())break;
        auto it=s.begin();
        node e=*it;s.erase(it);
        auto jt=s.lower_bound(node(e.b,e.a,inf,-1));
        if(jt==s.end())
        {
            if(e.a==e.b)
                sofar=max(sofar,e.c);
            continue;
        }
        if(e.b==jt->a and e.a==jt->b and (e.c+jt->c)>0)
        {
            ans+=(e.c+jt->c),s.erase(jt);
            if(e.a==e.b)
                sofar=max(sofar,-jt->c);
        }
        else if(e.a==e.b)
            sofar=max(sofar,e.c);
    }
    ans+=sofar;
    PLN(ans);
}


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

#define nl printf("\n")
#define pb(x) push_back(x)

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define P(a) printf("%d",a)

#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)

#define PL(a) printf("%lld",a)
#define PLN(a) printf("%lld\n",a)
#define PLC(a) printf("%lld ",a)
#define SL(a) scanf("%lld",&a)
#define SL2(a,b) scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SL4(a,b,c,d) scanf("%lld%lld%lld%lld",&a,&b,&c,&d)

#define CLR(a) memset(a,0,sizeof(a))
#define SET(a) memset(a,-1,sizeof(a))
#define FOOL(a) memset(a,false,sizeof(a))
#define fr(i,a,n) for(i=a;i<=n;i++)
#define frv(i,v) for(i=0;i<(int)v.size();i++)
#define frs(i,v) for(i=0;i<(int)v.length();i++)
#define pi acos(-1.0)
#define po 400001
#define co 1000000
#define mod 786433
#define inf 10000000

using namespace std;
ll f[100001];
struct node
{
    ll a,b,c,d;
    node(){};
    node(ll aa,ll bb,ll cc,ll dd){a=aa,b=bb,c=cc,d=dd;}
};
struct cmp
{
    bool operator()(const node& x,const node& y)const
    {
        if(x.a!=y.a)return x.a<y.a;
        if(x.b!=y.b)return x.b<y.b;
        if(x.c!=y.c)return x.c>y.c;
        return x.d<y.d;
    }
};
ll ptr=-1;
int main()
{
    string ss;
    ll k,n,x,y,i,z,ans=0,sofar;
    set<node,cmp> s;
    f[0]=1;
    fr(i,1,100000)
        f[i]=(f[i-1]*31LL)%mod;
    SL2(k,n);
    while(k--)
    {
        cin>>ss;
        x=0,y=0;
        frs(i,ss)
        {
            x=(x+(ss[i]-'a')*f[i])%mod;
            y=(y+(ss[i]-'a')*f[n-1-i])%mod;
        }
        SL(z);
            s.insert(node(x,y,z,++ptr));
    }
    sofar=0;
    while(1)
    {
        if(s.empty())break;
        auto it=s.begin();
        node e=*it;s.erase(it);
        auto jt=s.lower_bound(node(e.b,e.a,inf,-1));
        if(jt==s.end())
        {
            if(e.a==e.b)
                sofar=max(sofar,e.c);
            continue;
        }
        if(e.b==jt->a and e.a==jt->b and (e.c+jt->c)>0)
            ans+=(e.c+jt->c),s.erase(jt);
        else if(e.a==e.b)
            sofar=max(sofar,e.c);
    }
    ans+=sofar;
    PLN(ans);
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
using namespace std;

#define FR(i, a, b) for(int i = a; i < b; i++)
#define ROF(i, a, b) for(int i = a; i >= b; i--)
#define size(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define P_B push_back
#define F first
#define S second

typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

const int MAXN = 1000 * 1000 + 10;
//const int mod = 1000 * 1000 * 1000 + 7;
pair <string, pii> a[MAXN], b[MAXN];
bool mark[MAXN];

bool cmp(pair < string , pii> x, pair <string, pii> y)
{
	if(x.F < y.F) return true;
	if(x.F > y.F) return false;
	return x.S > y.S;
}

bool pal(const string &s)
{
	FR(i, 0, size(s) / 2)
		if(s[i] != s[size(s) - i - 1])
			return false;
	return true;
}

int main()
{
	ll n, k;
	cin>> n >> k;
	FR(i, 0, n)
	{
		cin>> a[i].F >> a[i].S.F;
		a[i].S.S = i;
		b[i] = a[i];
		reverse(all(b[i].F));
	}

	sort(a, a + n, cmp);
	sort(b, b + n, cmp);

	ll ans = 0;
	ll j = 0;
	FR(i, 0, n)
	{
		if(!mark[a[i].S.S])
			while(j < n && b[j].F <= a[i].F)
			{
				if(a[i].F == b[j].F && a[i].S.S != b[j].S.S)
					if(a[i].S.F + b[j].S.F > 0)
					{
						ans +=  a[i].S.F + b[j].S.F;
						mark[a[i].S.S] = true;
						mark[b[j].S.S] = true;
						j++;
						break;
					}
				j++;
			}
	}
	ll mx = 0;
	FR(i, 0, n)
		if(!mark[a[i].S.S] && pal(a[i].F))
			mx = max(mx, 1LL * a[i].S.F);

	cout<< ans + mx << endl;
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
using namespace std;

#define FR(i, a, b) for(int i = a; i < b; i++)
#define ROF(i, a, b) for(int i = a; i >= b; i--)
#define size(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define P_B push_back
#define F first
#define S second

typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <string, int> psi;

struct cmp{
	bool operator() (psi x, psi y)
	{
		if(x.F < y.F) return true;
		if(x.F > y.F) return false;
		return x.S > y.S;
	}
};

const int MAXN = 1000 * 1000 + 10;
//const int mod = 1000 * 1000 * 1000 + 7;
multiset <psi, cmp> st[2];
bool mark[MAXN];

bool pal(const string &s)
{
	FR(i, 0, size(s) / 2)
		if(s[i] != s[size(s) - i - 1])
			return false;
	return true;
}

int main()
{
	ll n, k;
	cin>> n >> k;
	FR(i, 0, n)
	{
		string s;
		int a;
		cin>> s >> a;
		if(pal(s))
			st[1].insert({s, a});
		else
			st[0].insert({s, a});
	}

	ll ans = 0;
	while(!st[0].empty())
	{
		psi cur = *st[0].begin();
		st[0].erase(st[0].begin());
		string w = cur.F;
		reverse(all(w));
		auto it = st[0].lower_bound({w, INT_MAX});
		if(it != st[0].end() && it -> F == w)
		{
			psi f = *it;
			if(f.S + cur.S > 0)
				ans += f.S + cur.S;
			st[0].erase(it);
		}
	}

	vector <int> str1;
	vector <pii> str2;
	while(!st[1].empty())
	{
		vector <psi> vec;
		string w = st[1].begin() -> F;
		while(!st[1].empty() && (st[1].begin()) -> F == w)
		{
			vec.P_B(*st[1].begin());
			st[1].erase(st[1].begin());
		}

		while(size(vec) >= 2 && vec[size(vec) - 2].S <= 0)
			vec.pop_back();

		int j = 0;
		while(j + 1 < size(vec) && vec[j + 1].S > 0)
		{
			ans += vec[j].S + vec[j + 1].S;
			j += 2;
		}
		if(j == size(vec) - 1 && vec[j].S > 0)
			str1.P_B(vec[j].S);
		if(j == size(vec) - 2)
			str2.P_B({vec[j].S, vec[j + 1].S});
	}

	ll sum = 0;
	FR(i, 0, size(str2))
		sum += max(str2[i].F + str2[i].S, 0);
	ll mx = 0;
	FR(i, 0, size(str2))
		mx = max(mx, sum - max(str2[i].F + str2[i].S, 0) + str2[i].F);
	FR(i, 0, size(str1))
		mx = max(mx, sum + str1[i]);
	cout<< ans + mx << endl;
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
using namespace std;

#define FR(i, a, b) for(int i = a; i < b; i++)
#define ROF(i, a, b) for(int i = a; i >= b; i--)
#define size(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define P_B push_back
#define F first
#define S second

typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <string, pair <ll, int> > psl;

const int MAXN = 1000 * 1000 + 10;
//const int mod = 1000 * 1000 * 1000 + 7;
psl a[MAXN], b[MAXN];
bool mark[MAXN];

bool cmp(psl x, psl y)
{
	if(x.F < y.F) return true;
	if(x.F > y.F) return false;
	return x.S > y.S;
}

bool pal(const string &s)
{
	FR(i, 0, size(s) / 2)
		if(s[i] != s[size(s) - i - 1])
			return false;
	return true;
}

int main()
{
	ll n, k;
	cin>> n >> k;
	FR(i, 0, n)
	{
		cin>> a[i].F >> a[i].S.F;
		a[i].S.S = i;
		b[i] = a[i];
		reverse(all(b[i].F));
	}

	sort(a, a + n, cmp);
	sort(b, b + n, cmp);

	ll ans = 0;
	ll j = 0;
	FR(i, 0, n)
	{
		if(!mark[a[i].S.S])
			while(j < n && b[j].F <= a[i].F)
			{
				if(a[i].F == b[j].F && a[i].S.S != b[j].S.S && a[i].S.F + b[j].S.F > 0)
				{
					ans += a[i].S.F + b[j].S.F;
					mark[a[i].S.S] = true;
					mark[b[j].S.S] = true;
					j++;
					break;
				}
				j++;
			}
	}
	ll mx = 0;
	FR(i, 0, n)
		if(!mark[a[i].S.S] && pal(a[i].F))
			mx = max(mx, 1LL * a[i].S.F);

	cout<< ans + mx << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MOD=1e9+7;

//const int MOD=998244353;

vector<long long> dp(1e7+1,-1);

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n,k;
    cin>>n>>k;

    map<string, vector<int>> np, pal;
    map<string, bool> vis;
    for(int i=0; i<n; i++){
        string s;
        int x;
        cin>>s>>x;
        string s2=s;
        reverse(s2.begin(),s2.end());
        if(s2!=s){
            vis[s]=0;
            np[s].push_back(x);
        }
        else{
            pal[s].push_back(x);
        }
    }
    int ans=0;
    for(auto p:np){
        if(vis[p.first]) continue;
        string s2=p.first;
        reverse(s2.begin(),s2.end());
        auto it=np.find(s2);
        if(it==np.end()) continue;
        int m=min(p.second.size(), it->second.size());
        vector<int> v1=p.second, v2=it->second;
        sort(v1.begin(),v1.end(),greater<int>());
        sort(v2.begin(),v2.end(),greater<int>());
        for(int i=0; i<m; i++){
            ans+=max(0,v1[i]+v2[i]);
        }
        vis[s2]=1;
        vis[p.first]=1;

    }

    int gain=0;
    for(auto p:pal){
        vector<int> v=p.second;
        sort(v.begin(),v.end(),greater<int>());
        for(int i=0; i<v.size() && v[i]>0; i+=2){
            if(i+1<v.size() && v[i+1]>=0){
                ans+=v[i]+v[i+1];
            }
            else if(i+1==v.size()){
                gain=max(gain,v[i]);
            }
            else if(i+1<v.size() && v[i+1]<0 && v[i]+v[i+1]>0){
                ans+=v[i]+v[i+1];
                gain=max(gain,v[i]+v[i+1]);
            }
        }
    }

    cout<<ans+gain;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MOD=1e9+7;

//const int MOD=998244353;

vector<long long> dp(1e7+1,-1);

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n,k;
    cin>>n>>k;

    map<string, vector<int>> np, pal;
    map<string, bool> vis;
    for(int i=0; i<n; i++){
        string s;
        int x;
        cin>>s>>x;
        string s2=s;
        reverse(s2.begin(),s2.end());
        if(s2!=s){
            vis[s]=0;
            np[s].push_back(x);
        }
        else{
            pal[s].push_back(x);
        }
    }
    int ans=0;
    for(auto p:np){
        if(vis[p.first]) continue;
        string s2=p.first;
        reverse(s2.begin(),s2.end());
        auto it=np.find(s2);
        if(it==np.end()) continue;
        int m=min(p.second.size(), it->second.size());
        vector<int> v1=p.second, v2=it->second;
        sort(v1.begin(),v1.end(),greater<int>());
        sort(v2.begin(),v2.end(),greater<int>());
        for(int i=0; i<m; i++){
            ans+=max(0,v1[i]+v2[i]);
        }
        vis[s2]=1;
        vis[p.first]=1;

    }

    int gain=0;
    for(auto p:pal){
        vector<int> v=p.second;
        sort(v.begin(),v.end(),greater<int>());
        for(int i=0; i<v.size() && v[i]>0; i+=2){
            if(i+1<v.size() && v[i+1]>=0){
                ans+=v[i]+v[i+1];
            }
            else if(i+1==v.size()){
                gain=max(gain,v[i]);
            }
            else if(i+1<v.size() && v[i+1]<0 && v[i]+v[i+1]>0){
                ans+=v[i]+v[i+1];
                gain=max(gain,-v[i+1]);
            }
        }
    }

    cout<<ans+gain;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MOD=1e9+7;

//const int MOD=998244353;

vector<long long> dp(1e7+1,-1);

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n,k;
    cin>>n>>k;

    map<string, vector<int>> np, pal;
    map<string, bool> vis;
    for(int i=0; i<n; i++){
        string s;
        int x;
        cin>>s>>x;
        string s2=s;
        reverse(s2.begin(),s2.end());
        if(s2!=s){
            vis[s]=0;
            np[s].push_back(x);
        }
        else{
            pal[s].push_back(x);
        }
    }
    int ans=0;
    for(auto p:np){
        if(vis[p.first]) continue;
        string s2=p.first;
        reverse(s2.begin(),s2.end());
        auto it=np.find(s2);
        if(it==np.end()) continue;
        int m=min(p.second.size(), it->second.size());
        vector<int> v1=p.second, v2=it->second;
        sort(v1.begin(),v1.end(),greater<int>());
        sort(v2.begin(),v2.end(),greater<int>());
        for(int i=0; i<m; i++){
            ans+=max(0,v1[i]+v2[i]);
        }
        vis[s2]=1;
        vis[p.first]=1;

    }

    int gain=0;
    for(auto p:pal){
        vector<int> v=p.second;
        sort(v.begin(),v.end(),greater<int>());
        for(int i=0; i<v.size() && v[i]>0; i+=2){
            if(i+1<v.size() && v[i+1]>=0){
                ans+=v[i]+v[i+1];
            }
            else if(i+1==v.size() || (i+1<v.size() && v[i+1]+v[i]<=0)){
                gain=max(gain,v[i]);
            }
            else if(i+1<v.size() && v[i+1]<0 && v[i]+v[i+1]>0){
                ans+=v[i]+v[i+1];
                gain=max(gain,-v[i+1]);
            }

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

    cout<<ans+gain;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int int64_t
#define endl '\n'
#define f first
#define s second

template <typename T>
ostream &operator<<(ostream & out, vector <T> arr){
    for (int i = 0; i < arr.size(); ++i)
        out << arr[i] << " ";
    return out;
}

template <typename T>
istream &operator>>(istream & in, vector <T> & arr){
    for (int i = 0; i < arr.size(); ++i)
        in >> arr[i];
    return in;
}

template <typename T1, typename T2>
ostream &operator<<(ostream & out, pair <T1, T2> & a){
    out << a.f << " " << a.s;
    return out;
}

template <typename T1, typename T2>
istream &operator>>(istream & in, pair <T1, T2> & a){
    in >> a.f >> a.s;
    return in;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    map <string, multiset <int> > m;
    int n, k;
    cin >> k >> n;
    string s;
    int a;
    vector <string> arr(k);
    vector <int> cost(k);
    for (int i = 0; i < k; ++i){
        cin >> s >> a;
        arr[i] = s;
        cost[i] = a;
        m[s].insert(-a);
    }

    vector <pair <int, int> > maxx;

    int ans = 0;
    for (auto i : m){
        bool flag = false;
        if (i.first != string(i.first.rbegin(), i.first.rend()))
            flag = true;

        if (flag && m.find(string(i.first.rbegin(), i.first.rend())) != m.end()){
            auto j = m.find(string(i.first.rbegin(), i.first.rend()));
            auto it1 = i.second.begin();
            auto it2 = j->second.begin();
            while (it1 != i.second.end() && it2 != j->second.end() && *it1 + *it2 < 0){
                ans -= *it1 + *it2;
                ++it1;
                ++it2;
            }
        }
        else if (!flag){
            auto it = i.second.begin();
            int cnt = 0;
            int sum = 0;
            int last = 0;
            while (it != i.second.end() && -*it > -1){
                cnt++;
                if (cnt % 2 == 0){
                    sum -= *it;
                    sum += last;
                }
                last = -*it;
                ++it;
            }
            //cout << i.f << " " << sum << " " << cnt << " " <<
            ans += 2 * sum;
            if (cnt % 2 == 1){
                int now = -last;
                if (it != i.second.end()){
                    now = -*it;
                }
                maxx.push_back({last, max(0ll, last + now)});
            }
        }
    }

    //ggojgogn

    ans /= 2;

    //cout << ans << endl;

    //for (auto i : maxx){
      //  cout << i.first << " " << i.second << endl;
    //}

    int max_ = 0;
    for (int i = 0; i < maxx.size(); ++i){

        ans += maxx[i].second;
        max_ = max(max_, maxx[i].first - maxx[i].second);
    }
    ans += max_;

    cout << ans << endl;
    //system("pause");
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int int64_t
#define endl '\n'
#define f first
#define s second

template <typename T>
ostream &operator<<(ostream & out, vector <T> arr){
    for (int i = 0; i < arr.size(); ++i)
        out << arr[i] << " ";
    return out;
}

template <typename T>
istream &operator>>(istream & in, vector <T> & arr){
    for (int i = 0; i < arr.size(); ++i)
        in >> arr[i];
    return in;
}

template <typename T1, typename T2>
ostream &operator<<(ostream & out, pair <T1, T2> & a){
    out << a.f << " " << a.s;
    return out;
}

template <typename T1, typename T2>
istream &operator>>(istream & in, pair <T1, T2> & a){
    in >> a.f >> a.s;
    return in;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    map <string, multiset <int> > m;
    int n, k;
    cin >> k >> n;
    string s;
    int a;
    vector <string> arr(k);
    vector <int> cost(k);
    for (int i = 0; i < k; ++i){
        cin >> s >> a;
        arr[i] = s;
        cost[i] = a;
        m[s].insert(-a);
    }

    vector <pair <int, int> > maxx;

    int ans = 0;
    for (auto i : m){
        bool flag = false;
        if (i.first != string(i.first.rbegin(), i.first.rend()))
            flag = true;

        if (flag && m.find(string(i.first.rbegin(), i.first.rend())) != m.end()){
            auto j = m.find(string(i.first.rbegin(), i.first.rend()));
            auto it1 = i.second.begin();
            auto it2 = j->second.begin();
            while (it1 != i.second.end() && it2 != j->second.end() && *it1 + *it2 < 0){
                ans -= *it1 + *it2;
                ++it1;
                ++it2;
            }
        }
        else if (!flag){
            auto it = i.second.begin();
            int cnt = 0;
            int sum = 0;
            int last = 0;
            while (it != i.second.end() && -*it > -1){
                cnt++;
                if (cnt % 2 == 0){
                    sum -= *it;
                    sum += last;
                }
                last = -*it;
                ++it;
            }
            //cout << i.f << " " << sum << " " << cnt << " " <<
            ans += 2 * sum;
            if (cnt % 2 == 1){
                int now = -last;
                if (it != i.second.end()){
                    now = -*it;
                }
                maxx.push_back({last, last + now});
            }
        }
    }

    ans /= 2;

    //cout << ans << endl;

    //for (auto i : maxx){
      //  cout << i.first << " " << i.second << endl;
    //}

    int max_ = 0;
    for (int i = 0; i < maxx.size(); ++i){
        ans += maxx[i].second;
        max_ = max(max_, maxx[i].first - maxx[i].second);
    }
    ans += max_;

    cout << ans << endl;
    //system("pause");
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int int64_t
#define endl '\n'
#define f first
#define s second

template <typename T>
ostream &operator<<(ostream & out, vector <T> arr){
    for (int i = 0; i < arr.size(); ++i)
        out << arr[i] << " ";
    return out;
}

template <typename T>
istream &operator>>(istream & in, vector <T> & arr){
    for (int i = 0; i < arr.size(); ++i)
        in >> arr[i];
    return in;
}

template <typename T1, typename T2>
ostream &operator<<(ostream & out, pair <T1, T2> & a){
    out << a.f << " " << a.s;
    return out;
}

template <typename T1, typename T2>
istream &operator>>(istream & in, pair <T1, T2> & a){
    in >> a.f >> a.s;
    return in;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    map <string, set <int> > m;
    int n, k;
    cin >> k >> n;
    string s;
    int a;
    vector <string> arr(k);
    vector <int> cost(k);
    for (int i = 0; i < k; ++i){
        cin >> s >> a;
        arr[i] = s;
        cost[i] = a;
        m[s].insert(-a);
    }

    vector <pair <int, int> > maxx;

    int ans = 0;
    for (auto i : m){
        bool flag = false;
        if (i.first != string(i.first.rbegin(), i.first.rend()))
            flag = true;

        if (flag && m.find(string(i.first.rbegin(), i.first.rend())) != m.end()){
            auto j = m.find(string(i.first.rbegin(), i.first.rend()));
            auto it1 = i.second.begin();
            auto it2 = j->second.begin();
            while (it1 != i.second.end() && it2 != j->second.end() && *it1 + *it2 < 0){
                ans -= *it1 + *it2;
                ++it1;
                ++it2;
            }
        }
        else if (!flag){
            auto it = i.second.begin();
            int cnt = 0;
            int sum = 0;
            int last = 0;
            while (it != i.second.end() && -*it > -1){
                cnt++;
                if (cnt % 2 == 0){
                    sum -= *it;
                    sum += last;
                }
                last = -*it;
                ++it;
            }
            //cout << i.f << " " << sum << " " << cnt << " " <<
            ans += 2 * sum;
            if (cnt % 2 == 1){
                int now = -last;
                if (it != i.second.end()){
                    now = -*it;
                }
                maxx.push_back({last, last + now});
            }
        }
    }

    ans /= 2;

    //cout << ans << endl;

    //for (auto i : maxx){
      //  cout << i.first << " " << i.second << endl;
    //}

    int max_ = 0;
    for (int i = 0; i < maxx.size(); ++i){
        ans += maxx[i].second;
        max_ = max(max_, maxx[i].first - maxx[i].second);
    }
    ans += max_;

    cout << ans << endl;
    //system("pause");
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int int64_t
#define endl '\n'
#define f first
#define s second

template <typename T>
ostream &operator<<(ostream & out, vector <T> arr){
    for (int i = 0; i < arr.size(); ++i)
        out << arr[i] << " ";
    return out;
}

template <typename T>
istream &operator>>(istream & in, vector <T> & arr){
    for (int i = 0; i < arr.size(); ++i)
        in >> arr[i];
    return in;
}

template <typename T1, typename T2>
ostream &operator<<(ostream & out, pair <T1, T2> & a){
    out << a.f << " " << a.s;
    return out;
}

template <typename T1, typename T2>
istream &operator>>(istream & in, pair <T1, T2> & a){
    in >> a.f >> a.s;
    return in;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    string s, t;
    cin >> s >> t;
    vector <set <int> > arr(26);
    for (int i = 0; i < s.size(); ++i){
        //if (s[i] != t[i]){
            arr[s[i] - 'a'].insert(t[i] - 'a');
            arr[t[i] - 'a'].insert(s[i] - 'a');
        //}
    }
    for (int i = 0; i < 26; ++i){
        if (arr[i].size() > 1){
            cout << -1 << endl;
            return 0;
        }
    }
    set <pair <char, char> > ans;
    for (int i = 0; i < 26; ++i){
        if (arr[i].size() > 0 && i != *arr[i].begin()){
            ans.insert({min(i + 'a', *arr[i].begin() + 'a'), max(i + 'a', *arr[i].begin() + 'a')});
        }
    }
    cout << ans.size() << endl;
    for (auto i : ans)
        cout << i.f << " " << i.s << endl;
    return 0;
}


#pragma GCC optimize("O3")

#include <bits/stdc++.h>

using namespace std;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

#define n_l '\n'
#define dbg(...) cout << "[" << #__VA_ARGS__ << "]: "; cout << to_string(__VA_ARGS__) << endl
template <typename T, size_t N> int SIZE(const T (&t)[N]){ return N; } template<typename T> int SIZE(const T &t){ return t.size(); } string to_string(const string s, int x1=0, int x2=1e9){ return '"' + ((x1 < s.size()) ? s.substr(x1, x2-x1+1) : "") + '"'; } string to_string(const char* s) { return to_string((string) s); } string to_string(const bool b) { return (b ? "true" : "false"); } string to_string(const char c){ return string({c}); } template<size_t N> string to_string(const bitset<N> &b, int x1=0, int x2=1e9){ string t = ""; for(int __iii__ = min(x1,SIZE(b)),  __jjj__ = min(x2, SIZE(b)-1); __iii__ <= __jjj__; ++__iii__){ t += b[__iii__] + '0'; } return '"' + t + '"'; } template <typename A, typename... C> string to_string(const A (&v), int x1=0, int x2=1e9, C... coords); int l_v_l_v_l = 0, t_a_b_s = 0; template <typename A, typename B> string to_string(const pair<A, B> &p) { l_v_l_v_l++; string res = "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; l_v_l_v_l--; return res; } template <typename A, typename... C> string to_string(const A (&v), int x1, int x2, C... coords) { int rnk = rank<A>::value; string tab(t_a_b_s, ' '); string res = ""; bool first = true; if(l_v_l_v_l == 0) res += n_l; res += tab + "["; x1 = min(x1, SIZE(v)), x2 = min(x2, SIZE(v)); auto l = begin(v); advance(l, x1); auto r = l; advance(r, (x2-x1) + (x2 < SIZE(v))); for (auto e = l; e != r; e = next(e)) { if (!first) { res += ", "; } first = false; l_v_l_v_l++; if(e != l){ if(rnk > 1) { res += n_l; t_a_b_s = l_v_l_v_l; }; } else{ t_a_b_s = 0; } res += to_string(*e, coords...); l_v_l_v_l--; } res += "]"; if(l_v_l_v_l == 0) res += n_l; return res; } void dbgm(){;} template<typename Heads, typename... Tails> void dbgm(Heads H, Tails... T){ cout << to_string(H) << " | "; dbgm(T...); }
#define dbgm(...) cout << "[" << #__VA_ARGS__ << "]: "; dbgm(__VA_ARGS__); cout << endl

#define REP(i,b) for(int i=0;i<(b);i++)
#define REPP(i,b) for(int i=1;i<=(b);i++)
#define PER(i,a,b) for(int i=(a);i>(b);i++)
#define SZ(a) int((a).size())
#define ALL(a) (a).begin(), (a).end()
#define MS(s) memset(s, 0, sizeof(s))
#define PB push_back
#define MP make_pair

typedef vector<pair<int, int>> VPII;
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = (int) 1e9 + 7;
string ascii_lowercase = "abcdefghijklmnopqrstuvwxyz";
string ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

struct hashLL { /* mp.rehash(n << 2); */
    size_t operator()(ll x) const {
        x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
        x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
        x = x ^ (x >> 31);
        return x;
    }
};

long long inv(long long a, long long b) {
    return 1 < a ? b - inv(b % a, a) * b / a : 1;
}

const ll INF = 1e6;

// unordered_map<int, int, custom_hash> mp;
// unordered_map<int, unordered_map<int, int, custom_hash>, custom_hash> g;

ll gcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0) {
        x = 0;
        y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd(b % a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll distsq(ll x1, ll y1, ll x2, ll y2) {
    return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
}
ll n, m, k, w;
string s;
unordered_map<string, vector<ll>> mp;
bool ispalindrome(const string& s) {
    int l = 0;
    int r = n - 1;
    while (l < r) {
        if (s[l++]!=s[r--]) return false;
    }
    return true;
}
int main() {
    // freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> k >> n;
    ll ans = 0;
    REP(i,k) {
        cin >> s >> w;
        mp[s].PB(w);
    }
    for (auto& pr : mp) sort(pr.second.rbegin(), pr.second.rend());
    unordered_set<string> seen;
    ll bestsingle = 0;
    ll remsm = 0;
    vector<pair<ll,ll>> v;
    for (auto pr : mp) {
        string wd = pr.first;
        if (seen.count(wd)) continue;
        bool pal = ispalindrome(wd);
        if (pal) {
            m = pr.second.size();
            for (int i = 0; i < m; i += 2) {
                if (i + 1 < m) {
                    if (pr.second[i] + pr.second[i+1] > 0) {
                        if (pr.second[i+1]>= 0) {
                            ans += pr.second[i] + pr.second[i+1];
                        } else {
                            v.PB(MP(pr.second[i], pr.second[i+1]));
                            remsm += pr.second[i] + pr.second[i+1];
                            break;
                        }
                    }
                } else {
                    bestsingle = max(bestsingle, pr.second[i]);
                    break;
                }
            }
        } else {
            string rev = wd;
            reverse(rev.begin(), rev.end());
            seen.emplace(rev);
            if (mp.count(rev)) {
                m = min(pr.second.size(), mp[rev].size());
                REP(i,m) {
                    if (pr.second[i] + mp[rev][i] > 0) ans += pr.second[i] + mp[rev][i];
                }
            }
        }
        seen.emplace(wd);
    }
    ll bestremsm = remsm + bestsingle;
    for (auto p : v) {
        bestremsm = max(bestremsm, remsm - p.second);
    }
    ans += bestremsm;
    cout << ans << endl;
    return 0;
}


#pragma GCC optimize("O3")

#include <bits/stdc++.h>

using namespace std;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

#define n_l '\n'
#define dbg(...) cout << "[" << #__VA_ARGS__ << "]: "; cout << to_string(__VA_ARGS__) << endl
template <typename T, size_t N> int SIZE(const T (&t)[N]){ return N; } template<typename T> int SIZE(const T &t){ return t.size(); } string to_string(const string s, int x1=0, int x2=1e9){ return '"' + ((x1 < s.size()) ? s.substr(x1, x2-x1+1) : "") + '"'; } string to_string(const char* s) { return to_string((string) s); } string to_string(const bool b) { return (b ? "true" : "false"); } string to_string(const char c){ return string({c}); } template<size_t N> string to_string(const bitset<N> &b, int x1=0, int x2=1e9){ string t = ""; for(int __iii__ = min(x1,SIZE(b)),  __jjj__ = min(x2, SIZE(b)-1); __iii__ <= __jjj__; ++__iii__){ t += b[__iii__] + '0'; } return '"' + t + '"'; } template <typename A, typename... C> string to_string(const A (&v), int x1=0, int x2=1e9, C... coords); int l_v_l_v_l = 0, t_a_b_s = 0; template <typename A, typename B> string to_string(const pair<A, B> &p) { l_v_l_v_l++; string res = "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; l_v_l_v_l--; return res; } template <typename A, typename... C> string to_string(const A (&v), int x1, int x2, C... coords) { int rnk = rank<A>::value; string tab(t_a_b_s, ' '); string res = ""; bool first = true; if(l_v_l_v_l == 0) res += n_l; res += tab + "["; x1 = min(x1, SIZE(v)), x2 = min(x2, SIZE(v)); auto l = begin(v); advance(l, x1); auto r = l; advance(r, (x2-x1) + (x2 < SIZE(v))); for (auto e = l; e != r; e = next(e)) { if (!first) { res += ", "; } first = false; l_v_l_v_l++; if(e != l){ if(rnk > 1) { res += n_l; t_a_b_s = l_v_l_v_l; }; } else{ t_a_b_s = 0; } res += to_string(*e, coords...); l_v_l_v_l--; } res += "]"; if(l_v_l_v_l == 0) res += n_l; return res; } void dbgm(){;} template<typename Heads, typename... Tails> void dbgm(Heads H, Tails... T){ cout << to_string(H) << " | "; dbgm(T...); }
#define dbgm(...) cout << "[" << #__VA_ARGS__ << "]: "; dbgm(__VA_ARGS__); cout << endl

#define REP(i,b) for(int i=0;i<(b);i++)
#define REPP(i,b) for(int i=1;i<=(b);i++)
#define PER(i,a,b) for(int i=(a);i>(b);i++)
#define SZ(a) int((a).size())
#define ALL(a) (a).begin(), (a).end()
#define MS(s) memset(s, 0, sizeof(s))
#define PB push_back
#define MP make_pair

typedef vector<pair<int, int>> VPII;
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = (int) 1e9 + 7;
string ascii_lowercase = "abcdefghijklmnopqrstuvwxyz";
string ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

struct hashLL { /* mp.rehash(n << 2); */
    size_t operator()(ll x) const {
        x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
        x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
        x = x ^ (x >> 31);
        return x;
    }
};

long long inv(long long a, long long b) {
    return 1 < a ? b - inv(b % a, a) * b / a : 1;
}

const ll INF = 1e6;

// unordered_map<int, int, custom_hash> mp;
// unordered_map<int, unordered_map<int, int, custom_hash>, custom_hash> g;

ll gcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0) {
        x = 0;
        y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd(b % a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll distsq(ll x1, ll y1, ll x2, ll y2) {
    return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
}
ll n, m, k, w;
string s;
unordered_map<string, vector<ll>> mp;
bool ispalindrome(const string& s) {
    int l = 0;
    int r = n - 1;
    while (l < r) {
        if (s[l++]!=s[r--]) return false;
    }
    return true;
}
int main() {
    // freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> k >> n;
    ll ans = 0;
    REP(i,k) {
        cin >> s >> w;
        mp[s].PB(w);
    }
    for (auto& pr : mp) sort(pr.second.rbegin(), pr.second.rend());
    unordered_set<string> seen;
    ll bestsingle = 0;
    ll remsm = 0;
    vector<pair<ll,ll>> v;
    for (auto pr : mp) {
        string wd = pr.first;
        if (seen.count(wd)) continue;
        bool pal = ispalindrome(wd);
        if (pal) {
            m = pr.second.size();
            for (int i = 0; i < m; i += 2) {
                if (i + 1 < m) {
                    if (pr.second[i] + pr.second[i+1] > 0) {
                        if (pr.second[i+1]>= 0) {
                            ans += pr.second[i] + pr.second[i+1];
                        } else {
                            v.PB(MP(pr.second[i], pr.second[i+1]));
                            remsm += pr.second[i] + pr.second[i+1];
                            break;
                        }
                    } else if (pr.second[i] > 0) {
                        bestsingle = max(bestsingle, pr.second[i]);
                        break;
                    }
                } else {
                    bestsingle = max(bestsingle, pr.second[i]);
                    break;
                }
            }
        } else {
            string rev = wd;
            reverse(rev.begin(), rev.end());
            seen.emplace(rev);
            if (mp.count(rev)) {
                m = min(pr.second.size(), mp[rev].size());
                REP(i,m) {
                    if (pr.second[i] + mp[rev][i] > 0) ans += pr.second[i] + mp[rev][i];
                }
            }
        }
        seen.emplace(wd);
    }
    ll bestremsm = remsm + bestsingle;
    for (auto p : v) {
        bestremsm = max(bestremsm, remsm - p.second);
    }
    ans += bestremsm;
    cout << ans << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	int lasta = 0, lastb = 0;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					lasta = beauty1;
					lastb = beauty2;
				}
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty()) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					lasta = beauty1;
					lastb = beauty2;
				}
			}
		}

//		cout << "MAPA SAD: " << endl;
//		printStruct(str);
	}

	int max = 0;

	if(lastb < 0 || lasta < 0) { max = -1 * findmin(lasta, lastb); }

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !str[rev].empty()) {
			max = str[rev].top() > max ? str[rev].top() : max;
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	int minTaken = 0x0FFFFFFF;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					minTaken = beauty1 < minTaken ? beauty1 : minTaken;
					minTaken = beauty2 < minTaken ? beauty2 : minTaken;
				}
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty()) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
				}
			}
		}

//		cout << rez << endl;
//		cout << "MAPA SAD: " << endl;
//		printStruct(str);

	}

	int max = 0;

	if(minTaken < 0) max = -1 * minTaken;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !str[rev].empty()) {
			max = str[rev].top() > max ? str[rev].top() : max;
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	int lasta = 0, lastb = 0;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					lasta = beauty1;
					lastb = beauty2;
				}
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty()) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					lasta = beauty1;
					lastb = beauty2;
				}
			}
		}

//		cout << "MAPA SAD: " << endl;
//		printStruct(str);
	}

	int max = 0;

	if(lastb < 0 || lasta < 0) {
		max = -1 * findmin(lasta, lastb);

	} else {
		for(auto &el : str) {
			string rev = el.first;
			reverse(rev.begin(), rev.end());

			if(rev == el.first && !str[rev].empty()) {
				max = str[rev].top() > max ? str[rev].top() : max;
			}
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	int minTaken = 0x0FFFFFFF;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev > el.first) continue;
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					minTaken = findmin(beauty1, minTaken);
					minTaken = findmin(beauty2, minTaken);
				} else {
					el.second.push(beauty1);
					el.second.push(beauty2);
					break;
				}
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty() && elRev.top() + el.second.top() >= 0) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				rez += beauty1 + beauty2;
			}
		}

//		cout << rez << endl;
//		cout << "MAPA SAD: " << endl;
//		printStruct(str);

	}

	int max = 0;

	if(minTaken < 0) max = -1 * minTaken;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !el.second.empty()) {
			max = findmax(max, el.second.top());
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		int revBeauty;
		if(str.count(rev) && !str[rev].empty()) {
			revBeauty = str[rev].top();
			str[rev].pop();
//			cout << rev << ": " << revBeauty << endl;
			if(!el.second.empty() && el.second.top() + revBeauty >= 0) {
				rez += el.second.top() + revBeauty;
				el.second.pop();
//				cout << rev << " i " << el.first << ", " << rez << endl;
			} else {
				str[rev].push(revBeauty);
			}
		}
//		cout << "MAPA SAD: " << endl;
//		printStruct(str);
	}

	int max = 0;
	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !str[rev].empty()) {
			max = str[rev].top() > max ? str[rev].top() : max;
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	int lasta = 0, lastb = 0;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					lasta = beauty1;
					lastb = beauty2;
				}
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty()) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					lasta = beauty1;
					lastb = beauty2;
				}
			}
		}

//		cout << "MAPA SAD: " << endl;
//		printStruct(str);
	}

	int max = 0xFFFFFFFF;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !str[rev].empty()) {
			max = str[rev].top() > max ? str[rev].top() : max;
		}
	}

	if( max <= 0 && (lastb < 0 || lasta < 0)) { max = -1 * findmin(lasta, lastb); }

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) rez += beauty1 + beauty2;
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty()) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				if(beauty2 + beauty1 >= 0) rez += beauty1 + beauty2;
			}
		}

//		cout << "MAPA SAD: " << endl;
//		printStruct(str);
	}

	int max = 0;
	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !str[rev].empty()) {
			max = str[rev].top() > max ? str[rev].top() : max;
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ulli;
typedef unsigned int ui;
typedef long long lli;
typedef long double ldb;

typedef pair<int, int> idBeauty;

int n, k, rez, id;
map <string, priority_queue<int> > str;

void printStruct(map<string, priority_queue<int> > el) {
	for(auto x : el) {
		cout << "\t" << x.first << ": ";
		while(!x.second.empty()) {
			cout << x.second.top() << " ";
			x.second.pop();
		}
		cout << endl;

	}
	cout << endl;
}

int findmax(int a, int b) { return a > b ? a : b; }
int findmin(int a, int b) { return a < b ? a : b; }

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> k;

	for(int i = 0; i < n; i++) {
		string s;
		int tmp;
		cin >> s >> tmp;

		str[s].push(tmp);
	}

//	printStruct(str);

	int minTaken = 0x0FFFFFFF;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());
		if(rev == el.first) {
			while(el.second.size() >= 2) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = el.second.top();
				el.second.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					minTaken = beauty1 < minTaken ? beauty1 : minTaken;
					minTaken = beauty2 < minTaken ? beauty2 : minTaken;
				}
			}
		} else {
			auto &elRev = str[rev];
			while(!el.second.empty() && !elRev.empty()) {
				int beauty1 = el.second.top();
				el.second.pop();
				int beauty2 = elRev.top();
				elRev.pop();

				if(beauty2 + beauty1 >= 0) {
					rez += beauty1 + beauty2;
					minTaken = beauty1 < minTaken ? beauty1 : minTaken;
					minTaken = beauty2 < minTaken ? beauty2 : minTaken;
				}
			}
		}

//		cout << "MAPA SAD: " << endl;
//		printStruct(str);
	}

	int max = 0;

	if(minTaken < 0) max = -1 * minTaken;

	for(auto &el : str) {
		string rev = el.first;
		reverse(rev.begin(), rev.end());

		if(rev == el.first && !str[rev].empty()) {
			max = str[rev].top() > max ? str[rev].top() : max;
		}
	}

	rez += max;

	cout << rez << endl;
	cout << endl;
	return 0;
}


#include <iostream>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <set>
#include <list>
#include <string>
#include <memory.h>
#include <bitset>
#include <stack>
using namespace std;
#define ll long long
#define ppi pair<ll , ll>
#define mp make_pair
const int MAX = 2e5 + 11, k = 31;
const int mod = 1e9 + 7 , phash = 31;
const int mod2 = 1e9 + 9 , phash2 = 31;
ppi getHash(string a)
{
	int sz = a.size();
	ll h = 0 , h2 = 0  , p = 1;
	for (int i = 0; i < sz; i++) {
		h = (h + (a[i] - 'a' + 1)*p) % mod;
		p = (p*phash) % mod;
	}
	p = 1;
	for (int i = 0; i < sz; i++)
	{
		h2 = (h2 + (a[i] - 'a' + 1)*p) % mod2;
		p = (p*phash2) % mod2;
	}
	return mp(h, h2);
}

ppi getHashRev(string a)
{
	reverse(a.begin(), a.end());
	return getHash(a);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("inp.txt", "r", stdin);
#endif
	int n, k;
	cin >> n >> k;
	map<ppi, vector<int>> hs;
	map<ppi, ppi> rev;
	for (int i = 0; i < n; i++)
	{
		string x; int b;
		cin >> x >> b;
		ppi h = getHash(x);
		ppi rh = getHashRev(x);
		hs[h].push_back(b);
		rev[h] = rh;
	}
	for (auto it = hs.begin(); it != hs.end(); it++)
		sort(it->second.begin(), it->second.end());
	ll sum = 0;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h == rh) continue;
		vector <int> & arr = it->second;
		vector <int> & arr2 = hs[rh];
		while (arr.size() && arr2.size())
		{
			if (arr.back() + arr2.back() > 0)
			{
				sum += arr.back() + arr2.back();
				arr.pop_back(); arr2.pop_back();
			}
			break;
		}
	}
	int mx = 0;
	vector<ppi> pr;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h != rh) continue;
		vector <int> & arr = it->second;
		if (arr.size() % 2 && arr.front() > 0)
			mx = max(mx, arr.front());
		for (int i = arr.size() - 1; i >= 1; i -= 2)
		{
			if (arr[i] > 0 && arr[i - 1] > 0)
				sum += arr[i] + arr[i - 1];
			else if (arr[i] + arr[i - 1] > 0) {
				pr.push_back(mp(arr[i - 1], arr[i]));
				sum += arr[i] + arr[i - 1];
			}
			else if (arr[i] >= 0)
				mx = max(mx, arr[i]);
		}
	}
	sort(pr.begin(), pr.end());
	if (!mx && pr.size()) sum += -pr.front().first;
	cout << mx + sum;
}


#include <iostream>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <set>
#include <list>
#include <string>
#include <memory.h>
#include <bitset>
#include <stack>
using namespace std;
#define ll long long
#define ppi pair<ll , ll>
#define mp make_pair
const int MAX = 2e5 + 11, k = 31;
const int mod = 1e9 + 7, phash = 31;
const int mod2 = 1e9 + 9, phash2 = 51;
ppi getHash(string a)
{
	int sz = a.size();
	ll h = 0, h2 = 0, p = 1;
	for (int i = 0; i < sz; i++) {
		h = (h + (a[i] - 'a' + 1)*p) % mod;
		p = (p*phash) % mod;
	}
	p = 1;
	for (int i = 0; i < sz; i++)
	{
		h2 = (h2 + (a[i] - 'a' + 1)*p) % mod2;
		p = (p*phash2) % mod2;
	}
	return mp(h, h2);
}

ppi getHashRev(string a)
{
	reverse(a.begin(), a.end());
	return getHash(a);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("inp.txt", "r", stdin);
#endif
	int n, k;
	cin >> n >> k;
	map<ppi, vector<int>> hs;
	map<ppi, ppi> rev;
	for (int i = 0; i < n; i++)
	{
		string x; int b;
		cin >> x >> b;
		ppi h = getHash(x);
		ppi rh = getHashRev(x);
		hs[h].push_back(b);
		rev[h] = rh;
	}
	for (auto it = hs.begin(); it != hs.end(); it++)
		sort(it->second.begin(), it->second.end());
	ll sum = 0;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h == rh) continue;
		vector <int> & arr = it->second;
		vector <int> & arr2 = hs[rh];
		while (arr.size() && arr2.size())
		{
			if (arr.back() + arr2.back() > 0)
			{
				sum += arr.back() + arr2.back();
				arr.pop_back(); arr2.pop_back();
			}
			else break;
		}
	}
	int mx = 0;
	vector<ppi> pr;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h != rh) continue;
		vector <int> & arr = it->second;
		if (arr.size() % 2 && arr.front() > 0)
			mx = max(mx, arr.front());
		for (int i = arr.size() - 1; i >= 1; i -= 2)
		{
			if (arr[i] > 0 && arr[i - 1] > 0)
			{
				sum += arr[i] + arr[i - 1];
			}
			else if (arr[i] + arr[i - 1] > 0)
			{
				pr.push_back(mp(arr[i - 1], arr[i]));
				sum += arr[i] + arr[i - 1];
				break;
			}
			else if (arr[i] >= 0)
				mx = max(mx, arr[i]);
		}
	}
	sort(pr.begin(), pr.end());
	if (pr.size() && -pr.front().first > mx) mx = -pr.front().first;
	cout << mx + sum;
}


#include <iostream>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <set>
#include <list>
#include <string>
#include <memory.h>
#include <bitset>
#include <stack>
using namespace std;
#define ll long long
#define ppi pair<ll , ll>
#define mp make_pair
const int MAX = 2e5 + 11, k = 31;
const int mod = 1e9 + 7 , phash = 51;
const int mod2 = 1e9 + 9 , phash2 = 31;
ppi getHash(string a)
{
	int sz = a.size();
	ll h = 0 , h2 = 0  , p = 1;
	for (int i = 0; i < sz; i++) {
		h = (h + (a[i] - 'a' + 1)*p) % mod;
		p = (p*phash) % mod;
	}
	p = 1;
	for (int i = 0; i < sz; i++)
	{
		h2 = (h2 + (a[i] - 'a' + 1)*p) % mod2;
		p = (p*phash2) % mod2;
	}
	return mp(h, h2);
}

ppi getHashRev(string a)
{
	reverse(a.begin(), a.end());
	return getHash(a);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("inp.txt", "r", stdin);
#endif
	int n, k;
	cin >> n >> k;
	map<ppi, vector<int>> hs;
	map<ppi, ppi> rev;
	for (int i = 0; i < n; i++)
	{
		string x;
		int b;
		cin >> x >> b;
		ppi h = getHash(x);
		ppi rh = getHashRev(x);
		hs[h].push_back(b);
		rev[h] = rh;
	}
	for (auto it = hs.begin(); it != hs.end(); it++)
		sort(it->second.begin(), it->second.end());
	int sum = 0;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		vector<int> & arr = it->second;
		while (arr.size())
		{
			int b = arr.back();
			arr.pop_back();
			if (hs[rh].size())
			{
				int s = hs[rh].back();
				hs[rh].pop_back();
				if (b + s > 0) sum += b + s;
				else
				{
					hs[rh].push_back(s);
					arr.push_back(b);
				}
			}
			else
			{
				arr.push_back(b);
				break;
			}
		}
	}
	int mx = 0;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h == rh && it->second.size())
		{
			mx = max(mx, it->second.back());
		}
	}
	cout << sum + mx << endl;
}


#include <iostream>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <set>
#include <list>
#include <string>
#include <memory.h>
#include <bitset>
#include <stack>
using namespace std;
#define ll long long
#define ppi pair<ll , ll>
#define mp make_pair
const int MAX = 2e5 + 11, k = 31;
const int mod = 1e9 + 7 , phash = 31;
const int mod2 = 1e9 + 9 , phash2 = 31;
ppi getHash(string a)
{
	int sz = a.size();
	ll h = 0 , h2 = 0  , p = 1;
	for (int i = 0; i < sz; i++) {
		h = (h + (a[i] - 'a' + 1)*p) % mod;
		p = (p*phash) % mod;
	}
	p = 1;
	for (int i = 0; i < sz; i++)
	{
		h2 = (h2 + (a[i] - 'a' + 1)*p) % mod2;
		p = (p*phash2) % mod2;
	}
	return mp(h, h2);
}

ppi getHashRev(string a)
{
	reverse(a.begin(), a.end());
	return getHash(a);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("inp.txt", "r", stdin);
#endif
	int n, k;
	cin >> n >> k;
	map<ppi, vector<int>> hs;
	map<ppi, ppi> rev;
	for (int i = 0; i < n; i++)
	{
		string x; int b;
		cin >> x >> b;
		ppi h = getHash(x);
		ppi rh = getHashRev(x);
		hs[h].push_back(b);
		rev[h] = rh;
	}
	for (auto it = hs.begin(); it != hs.end(); it++)
		sort(it->second.begin(), it->second.end());
	ll sum = 0;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h == rh) continue;
		vector <int> & arr = it->second;
		vector <int> & arr2 = hs[rh];
		while (arr.size() && arr2.size())
		{
			if (arr.back() + arr2.back() > 0)
			{
				sum += arr.back() + arr2.back();
				arr.pop_back(); arr2.pop_back();
			}
		}
	}
	int mx = 0;
	vector<ppi> pr;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h != rh) continue;
		vector <int> & arr = it->second;
		if (arr.size() % 2 && arr.front() > 0)
			mx = max(mx, arr.front());
		for (int i = arr.size() - 1; i >= 1; i -= 2)
		{
			if (arr[i] > 0 && arr[i - 1] > 0)
				sum += arr[i] + arr[i - 1];
			else if (arr[i] + arr[i - 1] > 0) {
				pr.push_back(mp(arr[i - 1], arr[i]));
				sum += arr[i] + arr[i - 1];
			}
			else if (arr[i] >= 0)
				mx = max(mx, arr[i]);
		}
	}
	sort(pr.begin(), pr.end());
	if (!mx && pr.size()) sum += -pr.front().first;
	cout << mx + sum;
}


#include <iostream>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <set>
#include <list>
#include <string>
#include <memory.h>
#include <bitset>
#include <stack>
using namespace std;
#define ll long long
#define ppi pair<ll , ll>
#define mp make_pair
const int MAX = 2e5 + 11, k = 31;
const int mod = 1e9 + 7 , phash = 31;
const int mod2 = 1e9 + 9 , phash2 = 31;
ppi getHash(string a)
{
	int sz = a.size();
	ll h = 0 , h2 = 0  , p = 1;
	for (int i = 0; i < sz; i++) {
		h = (h + (a[i] - 'a' + 1)*p) % mod;
		p = (p*phash) % mod;
	}
	p = 1;
	for (int i = 0; i < sz; i++)
	{
		h2 = (h2 + (a[i] - 'a' + 1)*p) % mod2;
		p = (p*phash2) % mod2;
	}
	return mp(h, h2);
}

ppi getHashRev(string a)
{
	reverse(a.begin(), a.end());
	return getHash(a);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("inp.txt", "r", stdin);
#endif
	int n, k;
	cin >> n >> k;
	map<ppi, vector<int>> hs;
	map<ppi, ppi> rev;
	for (int i = 0; i < n; i++)
	{
		string x; int b;
		cin >> x >> b;
		ppi h = getHash(x);
		ppi rh = getHashRev(x);
		hs[h].push_back(b);
		rev[h] = rh;
	}
	for (auto it = hs.begin(); it != hs.end(); it++)
		sort(it->second.begin(), it->second.end());
	ll sum = 0;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h == rh) continue;
		vector <int> & arr = it->second;
		vector <int> & arr2 = hs[rh];
		while (arr.size() && arr2.size())
		{
			if (arr.back() + arr2.back() > 0)
			{
				sum += arr.back() + arr2.back();
				arr.pop_back(); arr2.pop_back();
			}
			break;
		}
	}
	int mx = 0;
	vector<ppi> pr;
	for (auto it = hs.begin(); it != hs.end(); it++)
	{
		ppi h = it->first;
		ppi rh = rev[h];
		if (h != rh) continue;
		vector <int> & arr = it->second;
		if (arr.size() % 2 && arr.front() > 0)
			mx = max(mx, arr.front());
		for (int i = arr.size() - 1; i >= 1; i -= 2)
		{
			if (arr[i] > 0 && arr[i - 1] > 0)
			{
				sum += arr[i] + arr[i - 1];
			}
			else if (arr[i] + arr[i - 1] > 0) {
				pr.push_back(mp(arr[i - 1], arr[i]));
				sum += arr[i] + arr[i - 1];
			}
			else if (arr[i] >= 0)
				mx = max(mx, arr[i]);
		}
	}
	sort(pr.begin(), pr.end());
	if (pr.size() && -pr.front().first > mx) mx = -pr.front().first;
	cout << mx + sum;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const long long MAXN = 1e5 + 100;
const long long MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9999;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<long long>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (long long i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (long long i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

long long k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (long long i = 0; i < k; ++i){
        string str;
        long long cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    for (auto e : amount_hash){
        sort(e.second.begin(), e.second.end());
    }

    long long ans = 0;
    long long max_otm = 0;
    long long max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<long long> vec1 = e.second;
            vector<long long> vec2 = amount_hash[rev_hash[e.first]];

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<long long> vec1 = e.second;

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;
    cout << max_pl << ' ' << max_otm << endl;
    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const int MAXN = 1e5 + 100;
const int MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9999;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<int>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (int i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (int i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

int k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (int i = 0; i < k; ++i){
        string str;
        int cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    for (auto e : amount_hash){
        sort(e.second.begin(), e.second.end());
    }

    int ans = 0;
    int max_otm = 0;
    int max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<int> vec1 = e.second;
            vector<int> vec2 = amount_hash[rev_hash[e.first]];

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<int> vec1 = e.second;

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;
    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const long long MAXN = 1e5 + 100;
const long long MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9999;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<long long>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (long long i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (long long i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

long long k, n;
long long main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (long long i = 0; i < k; ++i){
        string str;
        long long cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    for (auto e : amount_hash){
        sort(e.second.begin(), e.second.end());
    }

    long long ans = 0;
    long long max_otm = 0;
    long long max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<long long> vec1 = e.second;
            vector<long long> vec2 = amount_hash[rev_hash[e.first]];

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<long long> vec1 = e.second;

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;
    cout << max_pl << ' ' << max_otm << endl;
    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const long long MAXN = 1e5 + 100;
const long long MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9999;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<long long>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (long long i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (long long i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

long long k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (long long i = 0; i < k; ++i){
        string str;
        long long cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    long long ans = 0;
    long long max_otm = 0;
    long long max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<long long> vec1 = e.second;
            sort(vec1.begin(), vec1.end());
            vector<long long> vec2 = amount_hash[rev_hash[e.first]];
            sort(vec2.begin(), vec2.end());

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<long long> vec1 = e.second;
            sort(vec1.begin(), vec1.end());

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;

    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const int MAXN = 1e5 + 100;
const int MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9999;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<int>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (int i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (int i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

int k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (int i = 0; i < k; ++i){
        string str;
        int cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    for (auto e : amount_hash){
        sort(e.second.begin(), e.second.end());
    }

    int ans = 0;
    int max_otm = 0;
    int max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<int> vec1 = e.second;
            vector<int> vec2 = amount_hash[rev_hash[e.first]];

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<int> vec1 = e.second;

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) > 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;
    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const long long MAXN = 1e5 + 100;
const long long MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9999;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<long long>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (long long i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (long long i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

long long k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (long long i = 0; i < k; ++i){
        string str;
        long long cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    for (auto e : amount_hash){
        sort(e.second.begin(), e.second.end());
    }

    long long ans = 0;
    long long max_otm = 0;
    long long max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<long long> vec1 = e.second;
            vector<long long> vec2 = amount_hash[rev_hash[e.first]];

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<long long> vec1 = e.second;

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;

    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const long long MAXN = 1e5 + 100;
const long long MAXK = 1e5 + 100;
const long long MOD = 1e9 + 7;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<long long>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (long long i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (long long i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

long long k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (long long i = 0; i < k; ++i){
        string str;
        long long cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    long long ans = 0;
    long long max_otm = 0;
    long long max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<long long> vec1 = e.second;
            sort(vec1.begin(), vec1.end());
            vector<long long> vec2 = amount_hash[rev_hash[e.first]];
            sort(vec2.begin(), vec2.end());

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<long long> vec1 = e.second;
            sort(vec1.begin(), vec1.end());

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;

    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;
const long long MAXN = 1e5 + 100;
const long long MAXK = 1e5 + 100;
const long long MOD = 1e9 + 9009;
const long long P = 257;

map<long long, long long> rev_hash;
map<long long, vector<long long>> amount_hash;

pair<long long, long long> get_hashes(string& str){
    long long h1 = 0;
    long long h2 = 0;

    for (long long i = 0; i < str.size(); ++i){
        h1 = ((h1 * P) + str[i]) % MOD;
    }

    for (long long i = str.size() - 1; i >= 0; --i){
        h2 = ((h2 * P) + str[i]) % MOD;
    }

    return {h1, h2};
}

long long k, n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> k >> n;
    for (long long i = 0; i < k; ++i){
        string str;
        long long cnt;
        cin >> str >> cnt;
        auto hs = get_hashes(str);
        rev_hash[hs.first] = hs.second;
        rev_hash[hs.second] = hs.first;
        amount_hash[hs.first].push_back(cnt);
    }

    long long ans = 0;
    long long max_otm = 0;
    long long max_pl = 0;
    for (auto e : amount_hash){
        if (e.first != rev_hash[e.first]){
            vector<long long> vec1 = e.second;
            sort(vec1.begin(), vec1.end());
            vector<long long> vec2 = amount_hash[rev_hash[e.first]];
            sort(vec2.begin(), vec2.end());

            while ((vec1.size() > 0) && (vec2.size() > 0) && (vec1[vec1.size() - 1] + vec2[vec2.size() - 1] > 0)){
                ans += vec1[vec1.size() - 1] + vec2[vec2.size() - 1];
                vec1.pop_back();
                vec2.pop_back();
            }
        } else {
            vector<long long> vec1 = e.second;
            sort(vec1.begin(), vec1.end());

            while (vec1.size() >= 2 && (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]) >= 0){
                if (vec1[vec1.size() - 2] < 0){
                    max_otm = max(max_otm, -vec1[vec1.size() - 2]);
                }
                ans += 2 * (vec1[vec1.size() - 1] + vec1[vec1.size() - 2]);
                vec1.pop_back();
                vec1.pop_back();
            }

            if (vec1.size() > 0){
                if (vec1[vec1.size() - 1] > 0){
                    max_pl = max(max_pl, vec1[vec1.size() - 1]);
                }
            }
        }
    }

    ans /= 2;

    cout << max(ans + max_pl, ans + max_otm) << endl;

    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        int S = UD[arr[i]].size();
        if(S){
            for(int j=M-1;j>=0;j--)
                rev.push_back(arr[i][j]);

                if(rev == arr[i]){
                    if(S > 1){
                        if(UD[arr[i]][S-1] + UD[arr[i]][S-2] > 0){
                            RESULT += UD[arr[i]][S-1] + UD[arr[i]][S-2];

                            UD[arr[i]].pop_back();
                            UD[arr[i]].pop_back();
                        }
                    }
                    else if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        if(UD[rev][F-1] + UD[arr[i]][S-1] > 0){
                            RESULT += UD[rev][F-1] + UD[arr[i]][S-1];

                            UD[rev].pop_back();
                            UD[arr[i]].pop_back();
                        }
                    }
                    else if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                }

                rev.clear();
        }
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
map< string, bool > used;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        if(UD[curS].empty()) arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        if(!UD[arr[i]].empty()){
            for(int j=M-1;j>=0;j--)
                    rev.push_back(arr[i][j]);

            while(!used[arr[i]]){
                int S = UD[arr[i]].size();
                if(S == 0) break;
                if(rev == arr[i]){
                    if(S > 1){
                        int L = UD[arr[i]][S-1], R = UD[arr[i]][S-2];

                        if(L + R <= 0){
                            used[arr[i]] = true;
                            s_part = max(s_part,L);
                        }
                        else{
                            RESULT += L + R;
                            UD[arr[i]].pop_back();
                            UD[arr[i]].pop_back();
                        }

                    }
                    else{
                        used[arr[i]] = true;
                        s_part = max(s_part,UD[arr[i]].back());
                    }
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        int L = UD[rev][F-1], R = UD[arr[i]][S-1];
                        if(L + R > 0){
                            RESULT += L + R;
                            UD[rev].pop_back();
                            UD[arr[i]].pop_back();
                        }
                        else used[arr[i]] = true;
                    }
                    else used[arr[i]] = true;
                }
            }
            rev.clear();
        }
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        int S = UD[arr[i]].size();
        if(S){
            for(int j=M-1;j>=0;j--)
                rev.push_back(arr[i][j]);

                if(rev == arr[i]){
                    if(S > 1){
                        int L = UD[arr[i]][S-1], R = UD[arr[i]][S-2];
                        if(L + R > 0){
                            RESULT += L + R;

                            UD[arr[i]].pop_back();
                            UD[arr[i]].pop_back();
                        }
                    }
                    else if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        int F = UD[rev][F-1], S = UD[arr[i]][S-1];
                        if(F + S > 0){
                            RESULT += F + S;

                            UD[rev].pop_back();
                            UD[arr[i]].pop_back();
                        }
                    }
                    else if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                }

                rev.clear();
        }
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e5+5;
const int MOD = 1e8;
const int INF = 2e9;

map< string, vector<int> > UD;
vector< string > arr;
int main(){
    long long RESULT = 0;
    int N = 0, M = 0, s_part = 0;
    scanf("%d%d",&N,&M);
    string curS = "", rev = "";
    int curI = 0;

    for(int i=1;i<=N;i++){
        cin >> curS;
        scanf("%d",&curI);

        if(UD[curS].empty()) arr.push_back(curS);
        UD[curS].push_back(curI);
    }
    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());
    for(int i=0;i<arr.size();i++){
        for(int j=arr[i].size()-1;j>=0;j--)
            rev.push_back(arr[i][j]);
        vector<int> F = UD[arr[i]], S = UD[rev];

        if(rev == arr[i]){
            int it = F.size()-1;
            for(;it > 0;it-=2){
                if(F[it-1] < 0) break;
                RESULT = RESULT + F[it] + F[it-1];
            }
            if(it == 0) s_part = max(s_part,F[0]);
            else if(it > 0){
                if(F[it] + F[it-1] < 0) s_part = max(s_part, F[it]);
                else s_part = max(s_part,-F[it-1]), RESULT = RESULT + F[it] + F[it-1];
            }
        }
        else{
            for(;!F.empty() && !S.empty();){
                if(F.back() + S.back() < 0) break;
                RESULT = RESULT + F.back() + S.back();
                F.pop_back(), S.pop_back(), UD[arr[i]].pop_back(), UD[rev].pop_back();
            }
        }
        rev.clear();
    }
    printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
map< string, bool > used;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        if(UD[curS].empty()) arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        if(!UD[arr[i]].empty()){
            for(int j=M-1;j>=0;j--)
                    rev.push_back(arr[i][j]);

            while(!used[arr[i]]){
                int S = UD[arr[i]].size();
                if(S == 0) break;
                if(rev == arr[i]){
                    if(S > 1){
                        int L = UD[arr[i]][S-1], R = UD[arr[i]][S-2];

                        if(L + R < 0){
                            used[arr[i]] = true;
                        }
                        else{
                            RESULT += L + R;
                            UD[arr[i]].pop_back();
                            UD[arr[i]].pop_back();
                        }

                    }
                    else{
                        used[arr[i]] = true;
                    }
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        int L = UD[rev][F-1], R = UD[arr[i]][S-1];
                        if(L + R > 0){
                            RESULT += L + R;
                            UD[rev].pop_back();
                            UD[arr[i]].pop_back();
                        }
                        else used[arr[i]] = true;
                    }
                    else used[arr[i]] = true;
                }
            }
            rev.clear();
        }
    }

    for(int i=0;i<arr.size();i++)
        if(UD[arr[i]].size() == 1)
            s_part = max(s_part, UD[arr[i]].back());

    for(int i=0;i<arr.size();i++){
        int L = UD[arr[i]].size();
         if(L > 1){
            int F = UD[arr[i]][L-1],S = UD[arr[i]][L-2];
            if(F > s_part && F - s_part > F - S){
                s_part = F;
                UD[arr[i]].pop_back();
            }
            else{
                RESULT = RESULT + F + S;
                UD[arr[i]].pop_back();
                UD[arr[i]].pop_back();
            }
         }
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
map< string, bool > used;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        if(UD[curS].empty()) arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        if(!UD[arr[i]].empty()){
            for(int j=M-1;j>=0;j--)
                    rev.push_back(arr[i][j]);

            while(!used[arr[i]]){
                int S = UD[arr[i]].size();
                if(S == 0) break;
                if(rev == arr[i]){
                    if(S > 1){
                        int L = UD[arr[i]][S-1], R = UD[arr[i]][S-2];

                        if(L + R < 0){
                            used[arr[i]] = true;
                        }
                        else{
                            RESULT += L + R;
                            UD[arr[i]].pop_back();
                            UD[arr[i]].pop_back();
                        }

                    }
                    else{
                        used[arr[i]] = true;
                    }
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        int L = UD[rev][F-1], R = UD[arr[i]][S-1];
                        if(L + R > 0){
                            RESULT += L + R;
                            UD[rev].pop_back();
                            UD[arr[i]].pop_back();
                        }
                        else used[arr[i]] = true;
                    }
                    else used[arr[i]] = true;
                }
            }
            rev.clear();
        }
    }

    for(int i=0;i<arr.size();i++){
        for(int j=M-1;j>=0;j--)
            rev.push_back(arr[i][j]);

        if(UD[arr[i]].size() == 1 && arr[i] == rev)
            s_part = max(s_part, UD[arr[i]].back());
        rev.clear();
    }

    for(int i=0;i<arr.size();i++){
        for(int j=M-1;j>=0;j--)
            rev.push_back(arr[i][j]);

        int L = UD[arr[i]].size();
         if(L > 1 && rev == arr[i]){
            int F = UD[arr[i]][L-1],S = UD[arr[i]][L-2];
            if(F > s_part && F - s_part > F - S){
                s_part = F;
                UD[arr[i]].pop_back();
            }
            else{
                RESULT = RESULT + F + S;
                UD[arr[i]].pop_back();
                UD[arr[i]].pop_back();
            }
         }
         rev.clear();
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        int S = UD[arr[i]].size();
        if(S){
            for(int j=M-1;j>=0;j--)
                rev.push_back(arr[i][j]);

                if(rev == arr[i]){
                    if(S > 1){
                        int L = UD[arr[i]][S-1], R = UD[arr[i]][S-2];
                        if(L + R > 0){
                            RESULT += L + R;

                            UD[arr[i]].pop_back();
                            UD[arr[i]].pop_back();
                        }
                    }
                    else if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        int L = UD[rev][F-1], R = UD[arr[i]][S-1];
                        if(L + R > 0){
                            RESULT += L + R;

                            UD[rev].pop_back();
                            UD[arr[i]].pop_back();
                        }
                    }
                    else if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                }

                rev.clear();
        }
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}


#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 1e3+5;
const int MOD = 1e9+7;
const int INF = 2e9;
map< string,vector<int> > UD;
map< string, bool > used;
vector< string > arr;
int main(){
    int N = 0, M = 0, s_part = -INF;
    long long RESULT = 0;
    scanf("%i%i",&N,&M);
    string curS = "";

    for(int i=1, curI = 0;i<=N;i++){
        cin >> curS;
        scanf("%i",&curI);

        if(UD[curS].empty()) arr.push_back(curS);
        UD[curS].push_back(curI);
    }

    for(int i=0;i<arr.size();i++)
        sort(UD[arr[i]].begin(),UD[arr[i]].end());

    string rev = "";
    for(int i=0;i<arr.size();i++){
        if(!UD[arr[i]].empty()){
            for(int j=M-1;j>=0;j--)
                    rev.push_back(arr[i][j]);

            while(!used[arr[i]]){
                int S = UD[arr[i]].size();
                if(S == 0) break;
                if(rev == arr[i]){
                    if(S > 1){
                        int L = UD[arr[i]][S-1], R = UD[arr[i]][S-2];
                        if(L + R > 0)
                            RESULT += L + R;

                        UD[arr[i]].pop_back();
                        UD[arr[i]].pop_back();
                    }
                    else{
                        used[arr[i]] = true;
                        if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                    }
                }
                else{
                    int F = UD[rev].size();
                    if(F){
                        int L = UD[rev][F-1], R = UD[arr[i]][S-1];
                        if(L + R > 0)
                            RESULT += L + R;

                        UD[rev].pop_back();
                        UD[arr[i]].pop_back();
                    }
                    else{
                        used[arr[i]] = true;
                        if(RESULT) s_part = max(s_part,UD[arr[i]].back());
                    }
                }
            }
            rev.clear();
        }
    }
    if(s_part < 0) printf("%I64d",RESULT);
    else printf("%I64d",RESULT + s_part);
    return 0;
}