#include <bits/stdc++.h>
using namespace std;
template <typename Tp>
inline void read(Tp &x) {
  static char c;
  static bool neg;
  x = 0, c = getchar(), neg = false;
  for (; !isdigit(c); c = getchar()) {
    if (c == '-') {
      neg = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (neg) {
    x = -x;
  }
}
const int N = 100000 + 5;
const int MOD = 979966511;
const int INF = 0x3f3f3f3f;
const int P = 233;
inline int hush(const char *str, int len) {
  int res = 0;
  for (int i = 0; i < len; ++i) {
    res = ((long long)res * P + str[i] - 'a') % MOD;
  }
  return res;
}
int k, n;
char str[N];
unordered_map<int, vector<int>> ori, rev, pal;
int main() {
  read(k), read(n);
  for (int i = 1, a, len, ho, hr; i <= k; ++i) {
    scanf("%s", str);
    read(a);
    len = strlen(str);
    ho = hush(str, len);
    reverse(str, str + len);
    hr = hush(str, len);
    if (ho == hr) {
      pal[ho].emplace_back(a);
    } else {
      ori[ho].emplace_back(a);
      rev[hr].emplace_back(a);
    }
  }
  long long ans = 0;
  for (auto &p : ori) {
    auto iter = rev.find(p.first);
    if (iter != rev.end()) {
      sort(p.second.begin(), p.second.end());
      sort(iter->second.begin(), iter->second.end());
      auto po = prev(p.second.end()), pr = prev(iter->second.end());
      while (*po + *pr > 0) {
        ans += *po + *pr;
        if (po == p.second.begin() || pr == iter->second.begin()) {
          break;
        }
        --po, --pr;
      }
    }
  }
  ans /= 2;
  int mn = INF, mx = -INF;
  for (auto &p : pal) {
    sort(p.second.begin(), p.second.end(), greater<int>());
    size_t cur = 0UL;
    for (size_t i = 0UL; i + 1 < p.second.size(); i += 2) {
      if (p.second[i] + p.second[i + 1] <= 0) {
        break;
      }
      ans += p.second[i] + p.second[i + 1];
      cur = i + 2;
      mn = std::min(mn, p.second[i + 1]);
    }
    if (cur < p.second.size()) {
      mx = std::max(mx, p.second[cur]);
    }
  }
  printf("%lld\n", std::max({ans - mn, ans, ans + mx}));
}
