Kirinriki
We define the distance of two strings A and B with same length n is
disA,B=∑i=0n−1|Ai−Bn−1−i|
The difference between the two characters is defined as the difference in ASCII.
You should find the maximum length of two non-overlapping substrings in given string S, and the distance between them are less then or equal to m.
Each case begins with one line with one integers m : the limit distance of substring.
Then a string S follow.
Limits
T≤100
0≤m≤5000
Each character in the string is lowercase letter, 2≤|S|≤5000
∑|S|≤20000
1
5
abcdefedcb
5
题目大意:给定一个字符串,问最大字串长度为多少的时候交叉相减的绝对值之和小于等于输入的m,注意,子串不能重合 。
题目分析:这道题目暴力肯定会超时,所以我们这里用到了二分的思想,先预处理总串中所有的字符串的长度,然后运用二分,因为任意两个不相交子串,都可以看作处于以某个位置为中心的对称位置上,枚举这个中心即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5005;
char s[5005];
unsigned short dp[maxn][maxn];///这里用int会超内存,所以用unsigned short
int len, m;
bool check(int mid)///用dp[i][j]数组记录字串i-j的dis,
///前半部分是A串,后半部分是B串,然后枚举n,二分查找
{
for(int i = 1; i <= len; i++)
{
if(i + mid*2-1 > len) break;
for(int j= i + mid; j <= len;j++)
{
if(j + mid - 1 > len) break;
if(dp[i][j+mid-1] - dp[i+mid][j-1] <= m)
return true;
}
}
return false;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &m);
scanf("%s", s+1);
len = strlen(s+1);///输入字符串的长度
for(int k = 1; k <= len; k++)///要求的字符串的长度
{
for(int i = 1; i <= len; i++)///字符串的起始位置
{
int j = i + k - 1; ///字符串的终点位置
if(j > len) break;
if(i == j) dp[i][j] = 0;
else if(j - i == 1) dp[i][j] = abs(s[i] - s[j]);
else dp[i][j] = dp[i+1][j-1] + abs(s[i] - s[j]);
}
}
int left = 1, right = len/2, mid, ans;
while(left <= right)///二分,枚举中心
{
mid = (left + right) >> 1;
if(check(mid))
{
ans = mid;
left = mid + 1;
}
else
right = mid - 1;
}
printf("%d\n", ans);
}
return 0;
}