Problem:
Problem F:
It Prefokery Pio
You are a member of a secret society named
Japanese Abekobe Group
, which is called J. A. G. for short.
Those who belong to this society often exchange encrypted messages. You received lots of encrypted
messages this morning, and you tried to decrypt them as usual. However, because you received so many
and long messages today, you had to give up decrypting them by yourself. So you decided to decrypt
them with the help of a computer program that you are going to write.
The encryption scheme in J. A. G. utilizes palindromes. A palindrome is a word or phrase that reads
the same in either direction. For example, “MADAM”, “REVIVER” and “SUCCUS” are palindromes,
while “ADAM”, “REVENGE” and “SOCCER” are not.
Specifically to this scheme, words and phrases made of only one or two letters are not regarded as
palindromes. For example, “A” and “MM” are not regarded as palindromes.
The encryption scheme is quite simple: each message is encrypted by inserting extra letters in such a
way that the longest one among all subsequences forming palindromes gives the original message. In
other words, you can decrypt the message by extracting the
longest palindrome subsequence
. Here, a
subsequence means a new string obtained by picking up some letters from a string without altering the
relative positions of the remaining letters. For example, the longest palindrome subsequence of a string
“YMAOKDOAMIMHAADAMMA” is “MADAMIMADAM” as indicated below by underline.
Now you are ready for writing a program.
Input
The input consists of a series of data sets. Each data set contains a line made of up to 2,000 capital
letters which represents an encrypted string.
The end of the input is indicated by EOF (end-of-file marker).
Output
For each data set, write a decrypted message in a separate line. If there is more than one decrypted
message possible (i.e. if there is more than one palindrome subsequence not shorter than any other ones),
you may write any of the possible messages.
You can assume that the length of the longest palindrome subsequence of each data set is always longer
than two letters.
Sample Input
YMAOKDOAMIMHAADAMMA
LELVEEL
Output for the Sample Input
MADAMIMADAM
LEVEL

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
//#include<atcoder/all>
using namespace std;
//using namespace atcoder;

using ll = long long;
using ld = long double;

//using mint = modint998244353;
//using mint = modint1000000007;

template<class T> using pq = priority_queue<T>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

#define vec_unique(v) v.erase(unique(v.begin(), v.end()), v.end()) //重複削除
#define vec_iota(v) iota(v.begin(), v.end(), 0) //0, 1, 2, 3, ..., n - 1にセット

int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
//int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
//int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};

#define INF 2e18
#define INF2 2e9

int main() {
    string s;
    while(cin >> s) {
        string t = s;
        reverse(t.begin(), t.end());
        int n = s.size();
        int m = t.size();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(s[i - 1] == t[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }

        //cout << dp[n][m] << endl;

        //LCSを復元
        int i = n;
        int j = m;
        string ans = "";
        while(i > 0 && j > 0) {
            if(s[i - 1] == t[j - 1]) {
                ans = s[i - 1] + ans;
                i--;
                j--;
            } else {
                if(dp[i][j] == dp[i][j - 1]) j--;
                else i--;
            }
        }
        cout << ans << endl;
    }
    //cout << fixed << setprecision(15) << << endl;
    return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 18752
final_rank: 5

code_snippet: // competitive-verifier: PROBLEM
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#if !defined(ATCODER) && !defined(EVAL)
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m) - 1; i >= int(n); --i)
#define FORL(i, m, n) for (std::int64_t i = (m); i < std::int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
struct increment_impl {
    template <class T>
    const increment_impl &operator>>(std::vector<T> &v) const {
        for (auto &x : v) ++x;
        return *this;
    }
} Inc;
struct decrement_impl {
    template <class T>
    const decrement_impl &operator>>(std::vector<T> &v) const {
        for (auto &x : v) --x;
        return *this;
    }
} Dec;
struct sort_impl {
    template <class T>
    const sort_impl &operator>>(std::vector<T> &v) const {
        std::sort(v.begin(), v.end());
        return *this;
    }
} Sort;
struct unique_impl {
    template <class T>
    const unique_impl &operator>>(std::vector<T> &v) const {
        std::sort(v.begin(), v.end());
        v.erase(std::unique(v.begin(), v.end()), v.end());
        return *this;
    }
} Uniq;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
int main(void) {
    string s;
    while (cin >> s) {
        int n = s.size();
        vector dp(n + 1, vector(n + 1, 0));
        rep (i, n) dp[i][i + 1] = 1;
        FOR (d, 2, n + 1) {
            rep (l, n) {
                int r = l + d;
                if (r > n)
                    break;
                dp[l][r] = max(dp[l + 1][r], dp[l][r - 1]);
                if (s[l] == s[r - 1])
                    chmax(dp[l][r], dp[l + 1][r - 1] + 2);
            }
        }
        string ans, rev;
        int l = 0, r = n;
        while (dp[l][r] > 0 && r - l > 1) {
            if (dp[l + 1][r - 1] + 2 == dp[l][r] && s[l] == s[r - 1]) {
                ans += s[l];
                rev += s[r - 1];
                ++l, --r;
            } else if (dp[l][r - 1] == dp[l][r]) {
                --r;
            } else {
                ++l;
            }
        }
        if (dp[l][r] > 0 && r - l > 0)
            ans += s[l];
        reverse(all(rev));
        ans += rev;
        co(ans);
    }
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 19120
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int longestCommonSubsequence(string s1, string s2) {
    int m = s1.length();
    int n = s2.length();
    vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
    
    for (int i=1; i<=m; i++) {
        for (int j=1; j<=n; j++) {
            if (s1[i-1] == s2[j-1]) {
                dp[i][j] = 1 + dp[i-1][j-1];
            } else {
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
    }
    
    return dp[m][n];
}

void printLCS(string s1, string s2) {
    int m = s1.length();
    int n = s2.length();
    vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
    
    for (int i=1; i<=m; i++) {
        for (int j=1; j<=n; j++) {
            if (s1[i-1] == s2[j-1]) {
                dp[i][j] = 1 + dp[i-1][j-1];
            } else {
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
    }
    
    string lcs;
    int i = m;
    int j = n;
    
    while (i > 0 && j > 0) {
        if (s1[i-1] == s2[j-1]) {
            lcs.push_back(s1[i-1]);
            i--;
            j--;
        } else if (dp[i-1][j] > dp[i][j-1]) {
            i--;
        } else {
            j--;
        }
    }
    
    for (int i=lcs.length()-1; i>=0; i--) {
        cout << lcs[i];
    }
    cout << endl;
}

int main() {
    string s;
    while (cin >> s) {
        string sReverse = s;
        reverse(sReverse.begin(), sReverse.end());
        printLCS(s, sReverse);
    }
    return 0;
}
accuracy: 1
time_ms: 460
memory_kb: 18832
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
string t;
string s;
int dp[2001][2001];
int lcs(int i , int j) {
    if(i == s.size() || j == t.size())return 0;
    int &res = dp[i][j];
    if(~res)return res;
    res = 0;
    if(s[i] == t[j])res = 1 + lcs(i + 1 , j + 1);
    else res = max(lcs(i + 1 , j) , lcs(i , j + 1));
    return res;
}
void build(int i , int j) {
    if(i == s.size() || j == t.size())return;
    if(s[i] == t[j]) {
        cout<<s[i];
        build(i + 1 , j + 1);
    }else {
        if(dp[i][j] == lcs(i + 1 ,j))build(i + 1 , j);
        else build(i , j + 1);
    }
}
signed main() {
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    while(cin>>s) {
        t = s;
        for(int i = 0;i < s.size();i++) {
            for(int j = 0;j < t.size();j++)
                dp[i][j] = -1;
        }
        reverse(t.begin() , t.end());
        int temp = lcs(0 , 0);
        build(0 , 0);
        cout<<'\n';
    }
}
accuracy: 1
time_ms: 800
memory_kb: 19188
final_rank: 9

code_snippet: #include <string>
#include <iostream>
#include <algorithm>
using namespace std;
string s; int dp[2009][2009];
int main() {
  while (cin >> s) {
    int n = s.size();
    for (int i = 0; i < n; i++) dp[i][i + 1] = 1;
    for (int i = 2; i <= n; i++) {
      for (int l = 0; l <= n - i; l++) {
        int r = l + i;
        dp[l][r] = max(dp[l + 1][r], dp[l][r - 1]);
        if (s[l] == s[r - 1]) dp[l][r] = max(dp[l][r], dp[l + 1][r - 1] + 2);
      }
    }
    string ret;
    int pl = 0, pr = n;
    while (pr - pl >= 2) {
      if (s[pl] == s[pr - 1] && dp[pl][pr] == dp[pl + 1][pr - 1] + 2) ret += s[pl], pl++, pr--;
      else if (dp[pl][pr] == dp[pl + 1][pr]) pl++;
      else pr--;
    }
    string ps = ret;
    if (pr - pl == 1) ps += s[pl];
    reverse(ret.begin(), ret.end());
    ps += ret;
    cout << ps << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 18444
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

// #define int long long
#define rep(i, n) for (long long i = (long long)(0); i < (long long)(n); ++i)
#define reps(i, n) for (long long i = (long long)(1); i <= (long long)(n); ++i)
#define rrep(i, n) for (long long i = ((long long)(n)-1); i >= 0; i--)
#define rreps(i, n) for (long long i = ((long long)(n)); i > 0; i--)
#define irep(i, m, n) for (long long i = (long long)(m); i < (long long)(n); ++i)
#define ireps(i, m, n) for (long long i = (long long)(m); i <= (long long)(n); ++i)
#define SORT(v, n) sort(v, v + n);
#define REVERSE(v, n) reverse(v, v+n);
#define vsort(v) sort(v.begin(), v.end());
#define all(v) v.begin(), v.end()
#define mp(n, m) make_pair(n, m);
#define cout(d) cout<<d<<endl;
#define coutd(d) cout<<std::setprecision(10)<<d<<endl;
#define cinline(n) getline(cin,n);
#define replace_all(s, b, a) replace(s.begin(),s.end(), b, a);
#define PI (acos(-1))
#define FILL(v, n, x) fill(v, v + n, x);
#define sz(x) long long(x.size())

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vs = vector<string>;
using vpll = vector<pair<ll, ll>>;
using vtp = vector<tuple<ll,ll,ll>>;
using vb = vector<bool>;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

const ll INF = 1e9;
const ll MOD = 1e9+7;
const ll LINF = 1e18;

ll dp[2005][2005]; // [l,r)における回文の最大長
string s;

void solve(){
  ll n=s.size();
  
  memset(dp,0,sizeof(dp));
  rep(i,n) dp[i][i+1]=1;
  
  for(ll len=2; len<=n; len++){
    for(ll i=0; i+len<=n; i++){
      ll j=i+len;
      if(s[i]==s[j-1]) chmax(dp[i][j],dp[i+1][j-1]+2);
      else chmax(dp[i][j],max(dp[i+1][j],dp[i][j-1]));
    }
  }
  
  ll ma=0, l,r;
  rep(i,n) irep(j,i,n+1){
    if(chmax(ma,dp[i][j])) l=i, r=j;
  }
  
  // cout<<dp[0][n]<<' '<<ma<<endl;
  
  if(ma==1){
    cout<<s[0]<<endl;
    return;
  }
  
  string left="", right="";
  while(ma>0){
    while(dp[l+1][r]==ma) l++;
    while(dp[l][r-1]==ma) r--;
    left+=s[l], right+=s[l];
    // cout<<l<<' '<<r<<' '<<ma<<endl;
    ma-=2;
    if(ma==1){
      left+=s[l+1];
      ma--;
    }
    l++, r--;
  }

  reverse(all(right));
  string ans=left+right;
  cout<<ans<<endl;
  
  return;
}


signed main()
{
  cin.tie( 0 ); ios::sync_with_stdio( false );
  
  for(int t = 0; cin >> s; t++) {
    solve();
  }
  
}
accuracy: 1
time_ms: 980
memory_kb: 34620
final_rank: 14

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>



int cal_longest_palindrome_subsequence(const std::string& str, const int left, const int right, std::vector<std::vector<int>>& memo) {
	if (left > right) return 0;
	if (left == right) return 1;
	if (memo[left][right - left - 1] >= 0) return memo[left][right - left - 1];
	if (str[left] == str[right]) memo[left][right - left - 1] = cal_longest_palindrome_subsequence(str, left + 1, right - 1, memo) + 2;
	return memo[left][right - left - 1] = std::max({ memo[left][right - left - 1], cal_longest_palindrome_subsequence(str, left + 1, right, memo), cal_longest_palindrome_subsequence(str, left, right - 1, memo) });
}
std::string make_longest_palindorome(const std::string& str) {
	std::string prev_half;
	std::vector<std::vector<int>> memo; memo.reserve(str.size());
	for (auto i = 0; i < str.size(); ++i) memo.push_back(std::vector<int>(str.size() - i, -1));
	for (int left = 0, right = str.size() - 1; left <= right; ) {
		if (str[left] == str[right]) {
			prev_half.push_back(str[left]); ++left; --right;
		}
		else if (cal_longest_palindrome_subsequence(str, left + 1, right, memo) > cal_longest_palindrome_subsequence(str, left, right - 1, memo)) {
			++left;
		}
		else {
			--right;
		}
	}
	const auto result_length = cal_longest_palindrome_subsequence(str, 0, str.size() - 1, memo);
	if (result_length % 2 == 1) {
		for (int i = prev_half.size() - 2; i >= 0; --i) prev_half.push_back(prev_half[i]);
	}
	else {
		for (int i = prev_half.size() - 1; i >= 0; --i) prev_half.push_back(prev_half[i]);
	}
	return prev_half;
}

int main() {
	std::string str;
	while (std::cin >> str) {
		std::cout << make_longest_palindorome(str) << '\n';
	}
}
accuracy: 1
time_ms: 1050
memory_kb: 10868
final_rank: 4

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;


int solve(int l, int r, const string& st,vector<vector<int>>&memo,vector<vector<int>>&flags) {
	if (memo[l][r] == -1) {
		if(l==r)memo[l][r]=0;
		else if(l+1==r)memo[l][r]=1;
		else {

			if (st[l] == st[r - 1]) {
				memo[l][r]=2+solve(l+1,r-1,st,memo,flags);
				flags[l][r]=3;
			}
			else {
				int lk=solve(l+1,r,st,memo,flags);
				int rk=solve(l,r-1,st,memo,flags);

				if (lk > rk) {
					flags[l][r]=2;
				}
				else {
					flags[l][r]=1;
				}
				memo[l][r]=max(lk,rk);
			}
		}
	}
	return memo[l][r];
}

int main() {
	string st;
	while (cin>>st) {
		vector<vector<int>>memo(st.size()+1,vector<int>(st.size()+1,-1)),flags(st.size()+1,vector<int>(st.size()+1));
		int ans=solve(0,st.size(),st,memo,flags);
		string ans_st1,ans_st2;

		int al=0;
		int ar=st.size();
		while (true) {
			int num=flags[al][ar];
			if (num == 3) {
				ans_st1.push_back(st[al]);
				ans_st2.push_back(st[ar-1]);
				al++;
				ar--;
			}
			else if (num == 2) {
				al++;
			}
			else if (num == 1) {
				ar--;
			}
			else {
				if (al + 1 == ar) {
					ans_st1.push_back(st[al]);

				}
				break;
			}
		}
		reverse(ans_st2.begin(),ans_st2.end());
		cout<<ans_st1<<ans_st2<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 1110
memory_kb: 34304
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
string s,t;
int dp[2011][2011];
int used[2011][2011];
string solve(){
  string ans="";
  int i=s.size()-1;
  int j=t.size()-1;
  while(i>0&&j>0){
    if(used[i][j]==1)ans+=t[j],i--,j--;
    else if(used[i][j]==2)i--;
    else j--;
  }
  return ans;
}
int main(){
  while(cin>>s){
    memset(dp,0,sizeof(dp));
    memset(used,0,sizeof(used));
    t=s;
    reverse(s.begin(),s.end());
    t="@"+t;
    s="@"+s;
    for(int i=1;i<s.size();i++)
      for(int j=1;j<t.size();j++)
    if(s[i]==t[j]){
      if(dp[i-1][j]>=dp[i-1][j-1]+1) dp[i][j]=max(dp[i][j],dp[i-1][j]),used[i][j]=2;
       
      else dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1),used[i][j]=1;
    }
        else{
      if(dp[i-1][j]>=dp[i][j-1])dp[i][j]=max(dp[i][j],dp[i-1][j]),used[i][j]=2;
      else dp[i][j]=max(dp[i][j],dp[i][j-1]),used[i][j]=3;
    }
    cout<<solve()<<endl;
  }
}
accuracy: 1
time_ms: 770
memory_kb: 34612
final_rank: 12

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


int dp[2001][2001];
int memo[2001][2001];

int main(){

	int length;
	char buf[2001],reverse[2001];
	stack<char> ANS;

	while(scanf("%s",buf) != EOF){

		for(length = 0; buf[length] != '\0'; length++);

		for(int i = 0; i < length; i++){
			reverse[i] = buf[length-1-i];
		}
		reverse[length] = '\0';

		for(int i = 0; i <= length; i++){
			for(int k = 0; k <= length; k++){
				dp[i][k] = 0;
			}
		}

		for(int i = 0; i < length; i++){
			for(int k = 0; k < length; k++){
				if(buf[i] == reverse[k]){
					dp[i+1][k+1] = dp[i][k]+1;
					memo[i+1][k+1] = 0;
				}else{
					if(dp[i][k+1] >= dp[i+1][k]){
						dp[i+1][k+1] = dp[i][k+1];
						memo[i+1][k+1] = 1;
					}else{
						dp[i+1][k+1] = dp[i+1][k];
						memo[i+1][k+1] = -1;
					}
				}
			}
		}

		for(int i = length,k = length; i > 0 && k > 0;){

			if(memo[i][k] == 1){
				i--;
			}else if(memo[i][k] == -1){
				k--;
			}else{ //memo[i][k] == 0
				ANS.push(buf[i-1]);
				i--;
				k--;
			}
		}

		while(!ANS.empty()){
			printf("%c",ANS.top());
			ANS.pop();
		}

		printf("\n");
	}

	return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 34288
final_rank: 10

code_snippet: #include<iostream>
#include<string>
#include<tuple>
#include<algorithm>
using namespace std;
string S; tuple<int, int, int>dp[2100][2100];
int solve(int s, int t) {
	if (s > t)return 0;
	if (get<0>(dp[s][t]) != -1)return get<0>(dp[s][t]);
	if (s == t) { dp[s][t] = make_tuple(1, -1, -1); return 1; }
	if (t - s == 1) {
		if (S[s] == S[t]) { dp[s][t] = make_tuple(2, -1, -1); return 2; }
	}
	int c1 = solve(s, t - 1);
	int c2 = solve(s + 1, t);
	int c3 = solve(s + 1, t - 1); if (S[s] == S[t])c3 += 2;
	if (c1 >= c2 && c1 >= c3) { dp[s][t] = make_tuple(c1, s, t - 1); return c1; }
	if (c2 >= c1 && c2 >= c3) { dp[s][t] = make_tuple(c2, s + 1, t); return c2; }
	if (c3 >= c1 && c3 >= c2) { dp[s][t] = make_tuple(c3, s + 1, t - 1); return c3; }
}
int main() {
	while (cin >> S) {
		for (int i = 0; i < S.size(); i++) { for (int j = 0; j < S.size(); j++)dp[i][j] = make_tuple(-1, 0, 0); }
		solve(0, S.size() - 1);
		string V, W; int F = 0, G = S.size() - 1;
		while (F + G >= 0) {
			int H = get<1>(dp[F][G]), I = get<2>(dp[F][G]);
			if (H == -1 || ((H - F) + (G - I)) == 2) {
				V += S[F]; if (F != G)W += S[F];
			}
			F = H; G = I;
		}
		reverse(W.begin(), W.end());
		cout << V + W << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 3150
memory_kb: 52512
final_rank: 20

code_snippet: #include <string>
#include <iostream>
#include <algorithm>
using namespace std;
string s; int dp[2009][2009];
int main() {
	while (cin >> s) {
		int n = s.size();
		for (int i = 0; i < n; i++) dp[i][i + 1] = 1;
		for (int i = 2; i <= n; i++) {
			for (int l = 0; l <= n - i; l++) {
				int r = l + i;
				dp[l][r] = max(dp[l + 1][r], dp[l][r - 1]);
				if (s[l] == s[r - 1]) dp[l][r] = max(dp[l][r], dp[l + 1][r - 1] + 2);
			}
		}
		string ret;
		int pl = 0, pr = n;
		while (pr - pl >= 2) {
			if (s[pl] == s[pr - 1] && dp[pl][pr] == dp[pl + 1][pr - 1] + 2) ret += s[pl], pl++, pr--;
			else if (dp[pl][pr] == dp[pl + 1][pr]) pl++;
			else pr--;
		}
		string ps = ret;
		if (pr - pl == 1) ps += s[pl];
		reverse(ret.begin(), ret.end());
		ps += ret;
		cout << ps << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 460
memory_kb: 16756
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define F first
#define S second
#define all(v) (v).begin(), (v).end()
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, f, n) for(int i = (int)(f); i < (int)(n); i++)
#define each(a, b) for(auto& a : b)

typedef pair<int, int> P;

int dp[2010][2010];
int tr[2010][2010];

signed main()
{
  string s;
  while(cin >> s) {
    string t = s; reverse(all(s));    
    memset(dp, 0, sizeof(dp));
    memset(tr, 0, sizeof(dp));
    for(int i = 0; i < s.size(); i++) {
      for(int j = 0; j < t.size(); j++) {
	if(s[i] == t[j]) dp[i+1][j+1] = dp[i][j] + 1, tr[i+1][j+1] = 1;
	else {
	  if(dp[i+1][j] > dp[i][j+1]) dp[i+1][j+1] = dp[i+1][j], tr[i+1][j+1] = 2;
	  else dp[i+1][j+1] = dp[i][j+1], tr[i+1][j+1] = 3;
	}
      }
    }
    string x;
    for(int i = s.size(), j = t.size(); i > 0 && j > 0; ) {
      switch(tr[i][j]) {
      case 1: x += s[i-1], i--, j--; break;
      case 2: j--; break;
      case 3: i--; break;
      }
    }
    cout << x << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 770
memory_kb: 34664
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define N 2050
string ss[2][N+1];
int c[N+1][N+1];
string lcs(string X,string Y){
  int m = X.size();
  int n = Y.size();
  int maxl = 0;
  X = ' ' + X;
  Y = ' ' + Y;
  ss[0][0] = "";
  memset(c,0,sizeof(c));
  for(int i=0;i<N+1;i++) ss[0][i]=ss[1][i]="";
  for(int i=0;i<=m;i++) c[i][0]=0;
  for(int j=1;j<=n;j++) c[0][j]=0;
  for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
      if(X[i]==Y[j]) c[i][j]=c[i-1][j-1]+1, ss[i%2][j] = ss[(i-1)%2][j-1] + X[i];
      else {
    if(c[i-1][j] >= c[i][j-1]) c[i][j]=c[i-1][j], ss[i%2][j] = ss[(i-1)%2][j];
    else c[i][j] = c[i][j-1], ss[i%2][j] = ss[i%2][j-1];
      }
      maxl=max(maxl,c[i][j]);
    }
  }
  string ret=ss[m%2][n],ret2=ret;
  reverse(ret2.begin(),ret2.end());
  //assert(ret==ret2);
  assert((int)ret.size()==maxl);
  return ss[m%2][n];
}
int main(){
  string s;
  while(cin >> s) {
    string t = s;
    reverse(t.begin(), t.end());
    cout << lcs(s, t) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 3720
memory_kb: 25592
final_rank: 19

code_snippet: #include<bits/stdc++.h>
#define N 2005
using namespace std;
string s,t,ans;
int dp[N][N];

void dfs(int y,int x){
  if(!y||!x)return;
  if(dp[y][x]-dp[y-1][x-1]==1&&dp[y][x]-dp[y-1][x]==1&&dp[y][x]-dp[y][x-1]==1){
    ans+=s[y-1];
    dfs(y-1,x-1);
    return;
  }
  if(dp[y][x-1]==dp[y][x])dfs(y,x-1);
  else dfs(y-1,x);
}

int main(){
  //IAIDDAII

    while(cin>>s){
      //s.resize(8);
      //for(int i=0;i<8;i++) s[i]='A'+(rand())%10;
      t=s;
    reverse(t.begin(),t.end());
    memset(dp,0,sizeof(dp));
    int n=s.size(),m=t.size();
    for(int i=0;i<n;i++){
      for(int j=0;j<m;j++){
	if(s[i]==t[j])dp[i+1][j+1]=dp[i][j]+1;
	else dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
      }
    }
    ans="";
    dfs(n,m);
    if(ans.size()%2==0){
      ans=ans.substr(0,ans.size()/2);
      string tmp=ans;reverse(tmp.begin(),tmp.end());
      ans=ans+tmp;
    }
    else {
      string tmp=ans.substr(0,ans.size()/2);
      reverse(tmp.begin(),tmp.end());
      ans=ans.substr(0,ans.size()/2)+ans[ans.size()/2]+tmp;
    }
    string temp=ans;
    reverse(temp.begin(),temp.end());
    assert(ans==temp);
    cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 18700
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define N 2050
string ss[2][N+1];
int c[N+1][N+1];
string lcs(string X,string Y){
  int m = X.size();
  int n = Y.size();
  int maxl = 0;
  X = ' ' + X;
  Y = ' ' + Y;
  ss[0][0] = "";
  memset(c,0,sizeof(c));
  for(int i=0;i<N+1;i++) ss[0][i]=ss[1][i]="";
  for(int i=0;i<=m;i++) c[i][0]=0;
  for(int j=1;j<=n;j++) c[0][j]=0;
  for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
      if(X[i]==Y[j]) c[i][j]=c[i-1][j-1]+1, ss[i%2][j] = ss[(i-1)%2][j-1] + X[i];
      else {
	if(c[i-1][j] >= c[i][j-1]) c[i][j]=c[i-1][j], ss[i%2][j] = ss[(i-1)%2][j];
	else c[i][j] = c[i][j-1], ss[i%2][j] = ss[i%2][j-1];
      }
      maxl=max(maxl,c[i][j]);
    }
  }
  string ret=ss[m%2][n],ret2=ret;
  reverse(ret2.begin(),ret2.end());
  //assert(ret==ret2);
  assert((int)ret.size()==maxl);
  return ss[m%2][n];
}
int main(){
  string s;
  while(cin >> s) {
    string t = s;
    reverse(t.begin(), t.end());
    cout << lcs(s, t) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 3700
memory_kb: 25592
final_rank: 18

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

#define TOPLEFT 0
#define TOP 1
#define LEFT 2
#define MAX 2000

void printLcs(string &l, vector<vector<short> > &b, const string &x, int i, int j, int k){
  if(i==0 || j==0) return;
  if(b[i][j]==TOPLEFT){
    printLcs(l, b, x, i-1, j-1, k-1);
    l[k] = x[i-1];
  }else if(b[i][j]==TOP){
    printLcs(l, b, x, i-1, j, k);
  }else{
    printLcs(l, b, x, i, j-1, k);
  }
}

void lcs(string &x, string &y, string &l){
  int m, n;
  vector<vector<short> > c, b;
  m = x.size();
  n = y.size();

  c.resize(m+1, vector<short>(n+1));
  b.resize(m+1, vector<short>(n+1));
  
  for(int i=0; i<=m; i++) c[i][0] = 0;
  for(int j=0; j<=n; j++) c[0][j] = 0;

  for(int i=1; i<=m; i++){
    for(int j=1; j<=n; j++){
      if(x[i-1]==y[j-1]){
	c[i][j] = c[i-1][j-1]+1;
	b[i][j] = TOPLEFT;
      }else if(c[i-1][j]>=c[i][j-1]){
	c[i][j] = c[i-1][j];
	b[i][j] = TOP;
      }else{
	c[i][j] = c[i][j-1];
	b[i][j] = LEFT;
      }
    }
  }

  l.resize(c[m][n]);

  printLcs(l, b, x, m, n, l.size()-1);
}

int main(){
    string s1, s2, l;
    while( cin >> s1 ){
	s2 = s1;
	reverse(s2.begin(), s2.end());
	lcs(s1, s2, l);
	cout << l << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 710
memory_kb: 18672
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define repi(i,a,b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i,n) repi(i,0,n)
 
string S;
int dp[2222][2222];
int trans[2222][2222];

int rec(int L, int R) {
  int& ret = dp[L][R];
  if(ret + 1) return ret;
  int& recons = trans[L][R];
  if(L > R) return ret = 0;
  if(S[L] == S[R]) {
    recons = 0;
    return ret = rec(L + 1, R - 1) + (L == R ? 1 : 2);
  }
 
  int r1 = rec(L + 1, R);
  int r2 = rec(L, R - 1);
 
  if(r1 > r2) {
    recons = 1;
    return ret = r1;
  }
  else {
    recons = 2;
    return ret = r2;
  }
 
}
 
int main() {
  while(cin >> S) {
 
    for(int i=0; i<2222; i++)
      for(int j=0; j<2222; j++)
        dp[i][j] = trans[i][j] = -1;
 
    int N = S.size();
    rec(0, N);
    int L = 0, R = N;
    string res;
    while(L < R) {
      if(trans[L][R] == 0) res += S[L], L ++, R --;
      if(trans[L][R] == 1) L ++;
      if(trans[L][R] == 2) R --;
    }
    cout << res;
    if(L == R) cout << S[L];
    reverse(res.begin(), res.end());
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1860
memory_kb: 41720
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define repi(i,a,b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i,n) repi(i,0,n)

string S;
int dp[2222][2222];
int trans[2222][2222];

const int rec(const int L, const int R) {
  int& ret = dp[L][R];
  if(ret + 1) return ret;
  if(L > R) return ret = 0;
  if(S[L] == S[R]) {
    trans[L][R] = 0;
    return ret = rec(L + 1, R - 1) + (L == R ? 1 : 2);
  }

  const int r1 = rec(L + 1, R);
  const int r2 = rec(L, R - 1);

  if(r1 > r2) {
    trans[L][R] = 1;
    return ret = r1;
  }
  else {
    trans[L][R] = 2;
    return ret = r2;
  }

}

int main() {
  while(cin >> S) {

    for(int i=0; i<2222; i++)
      for(int j=0; j<2222; j++)
        dp[i][j] = trans[i][j] = -1;

    int N = S.size();
    rec(0, N);
    int L = 0, R = N;
    string res;
    while(L < R) {
      if(trans[L][R] == 0) {
        res += S[L];
        L ++, R --;
      }
      if(trans[L][R] == 1) {
        L ++;
      }
      if(trans[L][R] == 2) {
        R --;
      }
    }
    cout << res;
    if(L == R) cout << S[L];
    reverse(res.begin(), res.end());
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1860
memory_kb: 41764
final_rank: 17

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<algorithm>	
#include<map>
#include<set>
#include<utility>
#include<cmath>
#include<cstring>
#include<queue>
#include<cstdio>
#include<sstream>
#include<iomanip>
#define loop(i,a,b) for(int i=a;i<b;i++) 
#define rep(i,a) loop(i,0,a)
#define pb push_back
#define mp make_pair
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
using namespace std;
//kaewasuretyuui
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef pair<int,pii> pip;
typedef vector<pip>vip;
const double PI=acos(-1);
const double EPS=1e-8;
const int inf=1e8;
const int LMAX=2010;
int dp[LMAX+1][LMAX+1],from[LMAX+1][LMAX+1];
string LCS(string &a,string &b){
	int m=a.size(),n=b.size();
	rep(i,m+1)dp[i][0]=0,from[i][0]=-1;
	rep(i,n+1)dp[0][i]=0,from[0][i]=-1;
	rep(i,m)rep(j,n){
		if(a[i]==b[j]){
			dp[i+1][j+1]=dp[i][j]+1;
			from[i+1][j+1]=2;
		}else{
			if(dp[i][j+1]<dp[i+1][j]){
				dp[i+1][j+1]=dp[i+1][j];
				from[i+1][j+1]=1;
			}else{
				dp[i+1][j+1]=dp[i][j+1];
				from[i+1][j+1]=0;
			}
		}
	}
	int idx=dp[m][n];
	string out(idx,'!');
	for(int i=m,j=n;~from[i][j];){
		switch(from[i][j]){
			case 0:i--;break;
			case 1:j--;break;
			case 2:i--;j--;idx--;out[idx]=a[i];break;
		}
	}
	return out;
}
int main(){
	string s;
	while(cin>>s){
		string t=s;
		reverse(all(t));
		cout<<LCS(s,t)<<endl;
	}
}
accuracy: 1
time_ms: 590
memory_kb: 32716
final_rank: 11