官方题解:两个不重合的子串向中心一起延长会形成奇偶长度两种合串。枚举一下中心向外延伸,如果和超过了阈值弹掉中心处的位置。双指针维护。时间复杂度O(n2 ) 另解:枚举[1,i],[j,n]用同样方法往内缩。时间复杂度O(n2 ) 。
思路:先枚举两个子串的对称轴向外延伸,将他们差值保存在一个数组里面再用尺取法求出最长的子序列的长度。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#include <string.h>
#include <cmath>
#include <sstream>
#include <set>
#include <map>
#include <functional>
#include <queue>
#include <vector>
using namespace std ;
const int maxn = 5010 ;
string str;
int num[maxn];
int t, m, res, len, cnt;
int solve()
{
int n = 0 , sum = 0 , ans = 0 , s = 0 ;
while (1 )
{
while (n < cnt&&sum+num[n] <= m)
{
sum += num[n++];
}
ans = max(n - s, ans);
sum -= num[s++];
if (n >= cnt)
break ;
}
return ans;
}
int main()
{
cin >> t;
while (t--)
{
cin >> m >> str;
len = str.length(), res = 0 , cnt;
for (int i = 0 ; i <=len ; i++)
{
cnt = 0 ;
for (int j = 1 ; i + j < len&&i - j >= 0 ; j++)
{
num[cnt++] = abs (str[i + j] - str[i - j]);
}
res = max(res, solve());
}
for (int i = 0 ; i <= len; i++)
{
cnt = 0 ;
for (int j = 1 ; i + j - 1 < len&&i - j >= 0 ; j++)
{
num[cnt++] = abs (str[i + j - 1 ] - str[i - j]);
}
res = max(res, solve());
}
cout << res << endl;
}
}
关键代码
void solve(){
int left = 0 , right = 0 , sum = 0 , res = n + 1 ;
while (true ){
while (right < n && sum < s)
{
sum += a [right ++];
}
if (sum < s)
break;
res = min (right - left, res);
sum -= a [left++];
}
if (res < n + 1 )
printf("%d\n" , res);
else
printf("0\n" );
}