class Solution {
public:
uint32_t getLength(
uint32_t nodeA,
uint32_t nodeB,
vector<vector<uint32_t>>& adjList,
string& label,
uint32_t & marked,
unordered_map<uint32_t, uint32_t>& memoPad
)
{
// Key is made up of nodeA, nodeB, and the set of nodes that are already in the palindrome.
uint32_t small = std::min(nodeA, nodeB);
uint32_t large = std::max(nodeA, nodeB);
uint32_t key = (100000000 * small) + (100000 * large) + marked;
if (memoPad.contains(key))
{
return memoPad[key];
}
if (label[nodeA] != label[nodeB] || nodeA == nodeB)
{
memoPad.insert({key, 0});
return memoPad[key];
}
uint32_t selfCount = 2; // Count NodeA and NodeB, they definitely match and are not the same node.
uint32_t maxCount = 0;
// For each combination of adjacent nodes to NodeA and NodeB call getLength().
for(uint32_t aaNIdx=0; aaNIdx<adjList[nodeA].size(); ++aaNIdx)
{
uint32_t aaNode = adjList[nodeA][aaNIdx];
if (inContainer(marked, aaNode)) { continue; }
insertIntoContainer(marked, aaNode);
for(uint32_t bbNIdx=0; bbNIdx<adjList[nodeB].size(); ++bbNIdx)
{
uint32_t bbNode = adjList[nodeB][bbNIdx];
if (inContainer(marked, bbNode)) {continue;}
insertIntoContainer(marked, bbNode);
uint32_t curCount = getLength(aaNode, bbNode, adjList, label, marked, memoPad);
maxCount = std::max(maxCount, curCount);
eraseFromContainer(marked, bbNode);
}
eraseFromContainer(marked, aaNode);
}
memoPad.insert({key, (maxCount + selfCount)});
return memoPad[key];
}
void insertIntoContainer(uint32_t& container, uint32_t number)
{
container |= (1 << number);
}
void eraseFromContainer(uint32_t& container, uint32_t number)
{
container &= (~( 1 << number));
}
bool inContainer(const uint32_t& container, const uint32_t& number)
{
return ( (container) & (1 << number)) > 0;
}
int maxLen(int n, vector<vector<int>>& edges, string label) {
// Longest palindrome length given the key as a uint32_t.
// The key is the sum of two nodes to be placed in the palidrome and the set of nodes that are already in the palindrome.
// The set of nodes that are already in the palindrome are represented by seen, a uint32_t.
unordered_map<uint32_t, uint32_t> memoPad{};
// adjaceny list.
vector<vector<uint32_t>> adjList(n, vector<uint32_t>{});
for(const vector<int>& edge : edges)
{
adjList[edge[0]].push_back(edge[1]);
adjList[edge[1]].push_back(edge[0]);
}
// nodeB is central node in the palindrome.
// Case where the palindrome length is odd. Take each letter (nodeB), put it in the container seen (which holds all the nodes in the palindrome).
// Take all combinations of adjacent letters to nodeB and call getLength().
uint32_t seen = 0;
uint32_t maxCount = 1; // Count nodeB as 1. May be a palindrome of length one.
for(uint32_t nodeB=0; nodeB<n; ++nodeB)
{
insertIntoContainer(seen, nodeB);
for(uint32_t ii=0; ii<adjList[nodeB].size(); ++ii)
{
uint32_t nodeA = adjList[nodeB][ii];
insertIntoContainer(seen, nodeA);
for(uint32_t jj=ii+1; jj<adjList[nodeB].size(); ++jj)
{
uint32_t nodeC = adjList[nodeB][jj];
insertIntoContainer(seen, nodeC);
uint32_t count = getLength(nodeA, nodeC, adjList, label, seen, memoPad);
eraseFromContainer(seen, nodeC);
maxCount = std::max(maxCount, count + 1);
}
eraseFromContainer(seen, nodeA);
}
eraseFromContainer(seen, nodeB);
}
// Find the longest length if there is no center of palindrome.
for(uint32_t nodeA=0; nodeA<n; ++nodeA)
{
insertIntoContainer(seen, nodeA);
for(uint32_t ii=0; ii<adjList[nodeA].size(); ++ii)
{
uint32_t nodeB = adjList[nodeA][ii];
insertIntoContainer(seen, nodeB);
uint32_t count = getLength(nodeA, nodeB, adjList, label, seen, memoPad);
eraseFromContainer(seen, nodeB);
maxCount = std::max(maxCount, count);
}
eraseFromContainer(seen, nodeA);
}
return maxCount;
}
};