题意:一个长度为 n 的数组 a,当 ai ≠ ai+1时可以将 ai 和 ai+1 从数组 a 中删去,求数组 a 中所有数相同,数组最长能是多少。
思路:我们用 dp[i] 表示以 i 为结尾的答案数组长度,当 a[j] 与 a[i] 相同并且中间所有数都能删除时,dp[j] = max(dp[j], dp[i] + 1)。并且作为答案数组要保证第一个数前面的所有数能删除,并且最后一个数后面所有的数能删除。然后我们只要先预处理所有子串是否能删除,就能求出答案。一个长度为 l 的子串,如果要能被删除,l 必须是偶数并且子串中出现次数最多的次数不大于 l / 2。
代码:
#include<bits/stdc++.h>
#define pb push_back
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10, P = 1e9 + 7, mod = 998244353;
int a[N];
int f[5100][5100], dp[5100];
void solve() {
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) {
int m = 0;
vector<int> c(n + 1);
c[a[i]]++, m = max(m, c[a[i]]);
for(int j = i + 1; j <= n; j++) {
c[a[j]]++, m = max(m, c[a[j]]);
int l = j - i;
if(l & 1 && m <= (l + 1) / 2) f[i][j] = 1;
else f[i][j] = 0;
}
}
for(int i = 1; i <= n; i++) {
if(i == 1 || f[1][i - 1]) dp[i] = 1;
else dp[i] = 0;
}
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
if(dp[i] && a[j] == a[i] && (j == i + 1 || f[i + 1][j - 1]))
dp[j] = max(dp[j], dp[i] + 1);
}
}
int ans = 0;
for(int i = 1; i <= n; i++)
if(f[i + 1][n] || i == n) ans = max(ans, dp[i]);
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int tt = 1;
cin >> tt;
while(tt--) {
solve();
}
return 0;
}