Problem Statement:
An airline planner has an itinerary string representing a sequence of airport codes joined by hyphens, e.g.,
"SFO-LAX-SEA-LAX-SFO-BOS"
A subsequence of this itinerary is obtained by deleting zero or more airport codes without changing the order of the remaining codes. Find the length of the longest subsequence of airport codes that reads the same forwards and backwards (i.e., a palindromic subsequence), so the planner can identify the largest symmetric round-trip segment.
Example:
itinerary = "NYC-LAX-CHI-LAX-NYC-BOS"
Output: 5 // One palindromic subsequence is ["NYC", "LAX", "CHI", "LAX", "NYC"]
Constraints:
Sample Input:
MNO-PQR-STU-PQR-MNO
Sample Output:
5
Problem Solution
The objective is to find the Longest Palindromic Subsequence (LPS) of airport codes. Unlike a substring, a subsequence does not need to be contiguous; you can delete codes from the original itinerary as long as you maintain the relative order of the remaining ones. A "palindromic" subsequence reads the same forwards and backwards (e.g., ["SFO", "LAX", "SFO"]).
With N \le 4000 codes, a standard recursive approach with memoization or a 2D dynamic programming approach is required to solve this in O(N^2) time.
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
int longestSymmetricItinerary(string itinerary) {
// Step 1: Tokenize the itinerary by hyphens
vector<string> codes;
stringstream ss(itinerary);
string token;
while (getline(ss, token, '-')) {
if (!token.empty()) {
codes.push_back(token);
}
}
int n = codes.size();
if (n == 0) return 0;
// Step 2: Initialize DP table
// dp[i][j] = length of LPS in codes[i...j]
// Using a 1D vector to simulate 2D for memory efficiency if needed,
// but N=4000 fits in a standard 2D vector (64MB).
vector<vector<int>> dp(n, vector<int>(n, 0));
// Every single airport is a palindrome of length 1
for (int i = 0; i < n; i++) {
dp[i][i] = 1;
}
// Step 3: Build the DP table for segments of increasing length
for (int len = 2; len <= n; len++) {
for (int i = 0; i <= n - len; i++) {
int j = i + len - 1;
if (codes[i] == codes[j]) {
// If boundary codes match, they add 2 to the inner result
// If len is 2, dp[i+1][j-1] is effectively 0
dp[i][j] = (len == 2) ? 2 : dp[i + 1][j - 1] + 2;
} else {
// Otherwise, take the maximum of moving either boundary
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
// The result for the full range
return dp[0][n - 1];
}
int main() {
string input;
if (cin >> input) {
cout << longestSymmetricItinerary(input) << endl;
}
return 0;
}