#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
string theString; //HACK
int n;
vector<vector<int> > _memo;
int f(int i, int j); // Need forward declaration for mutual recursion
int m(int i, int j) {
return static_cast<int>(theString[i - 1] == theString[j - 1] && i < j) + f(i - 1, j - 1);
}
int f(int i, int j) {
if (i == 0 || j == 0) {
return 0;
}
// Make sure the DP table is big enough
if (_memo.size() <= i) {
_memo.resize(i + 1);
}
if (_memo[i].size() <= j) {
_memo[i].resize(j + 1, -1); // -1 means "dunno yet"
}
if (_memo[i][j] == -1) {
// Dunno the answer yet, need to compute it
_memo[i][j] = max(max(f(i - 1, j), f(i, j - 1)), m(i, j));
}
return _memo[i][j];
}
int longestSACS(string s) {
// Clear the DP table
_memo.clear();
theString = s;
n = theString.size();
int x = 0;
for (int i = 0; i <= n; ++i) {
x = max(x, f(i, n));
}
return x;
}
int main(int argc, char **argv) {
cout << longestSACS("1213213515") << '\n';
cout << longestSACS("1213243545") << '\n';
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnN0cmluZyB0aGVTdHJpbmc7CQkvL0hBQ0sKaW50IG47CnZlY3Rvcjx2ZWN0b3I8aW50PiA+IF9tZW1vOwoKaW50IGYoaW50IGksIGludCBqKTsJCS8vIE5lZWQgZm9yd2FyZCBkZWNsYXJhdGlvbiBmb3IgbXV0dWFsIHJlY3Vyc2lvbgoKaW50IG0oaW50IGksIGludCBqKSB7CglyZXR1cm4gc3RhdGljX2Nhc3Q8aW50Pih0aGVTdHJpbmdbaSAtIDFdID09IHRoZVN0cmluZ1tqIC0gMV0gJiYgaSA8IGopICsgZihpIC0gMSwgaiAtIDEpOwp9CgppbnQgZihpbnQgaSwgaW50IGopIHsKCWlmIChpID09IDAgfHwgaiA9PSAwKSB7CgkJcmV0dXJuIDA7Cgl9CgkKCS8vIE1ha2Ugc3VyZSB0aGUgRFAgdGFibGUgaXMgYmlnIGVub3VnaAoJaWYgKF9tZW1vLnNpemUoKSA8PSBpKSB7CgkJX21lbW8ucmVzaXplKGkgKyAxKTsKCX0KCWlmIChfbWVtb1tpXS5zaXplKCkgPD0gaikgewoJCV9tZW1vW2ldLnJlc2l6ZShqICsgMSwgLTEpOwkJLy8gLTEgbWVhbnMgImR1bm5vIHlldCIKCX0KCQoJaWYgKF9tZW1vW2ldW2pdID09IC0xKSB7CgkJLy8gRHVubm8gdGhlIGFuc3dlciB5ZXQsIG5lZWQgdG8gY29tcHV0ZSBpdAoJCV9tZW1vW2ldW2pdID0gbWF4KG1heChmKGkgLSAxLCBqKSwgZihpLCBqIC0gMSkpLCBtKGksIGopKTsKCX0KCQoJcmV0dXJuIF9tZW1vW2ldW2pdOwp9CgppbnQgbG9uZ2VzdFNBQ1Moc3RyaW5nIHMpIHsKCS8vIENsZWFyIHRoZSBEUCB0YWJsZQoJX21lbW8uY2xlYXIoKTsKCXRoZVN0cmluZyA9IHM7CgluID0gdGhlU3RyaW5nLnNpemUoKTsKCQoJaW50IHggPSAwOwoJZm9yIChpbnQgaSA9IDA7IGkgPD0gbjsgKytpKSB7CgkJeCA9IG1heCh4LCBmKGksIG4pKTsKCX0KCQoJcmV0dXJuIHg7Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyICoqYXJndikgewoJY291dCA8PCBsb25nZXN0U0FDUygiMTIxMzIxMzUxNSIpIDw8ICdcbic7Cgljb3V0IDw8IGxvbmdlc3RTQUNTKCIxMjEzMjQzNTQ1IikgPDwgJ1xuJzsKCXJldHVybiAwOwp9Cg==