题意:
给出一个字符串s,找其两个长度相同且不重叠的子串,满足两个子串相对应的每位ASCLL码差值绝对值之和不大于m,求满足条件的最长子串长度。
思路:
由于单个数据长度才5000,所以可以想一个枚举的思路。
可以将主串分成前后两个等长的子串,第二个串进行一次反向,然后我们可以将两个串上下对齐,然后进行下述操作:上串保持不动,下串一直往后挪,,当上串的相对位置比下串少1个时,下串末尾移至上传末尾(不正好是原串中这个上串的下一个位置的字符嘛),在每一次挪动中,就进行第二个串长度的一次尺取。最后再将串反向进行上述操作一次,就将全部的可能都考虑到了。假如s串为abcdefghi,操作如下:
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
char s[maxn], s1[maxn], s2[maxn];
int m, t, ans, mlen;
void work()
{
int len1, len2;
len1 = len2 = mlen/2;
if(mlen & 1) ++len2;
strcpy(s1, s); s1[len1] = '\0';
strcpy(s2, s+len1); s2[len2] = '\0';
reverse(s2, s2+len2);
for(int k = 0; k < len1; ++k)
{
int q1, h1, q2, h2;
int now = 0;
q1 = k, q2 = 0;
h1 = k, h2 = 0;
while(h1 < len1)
{
now += abs(s1[h1]-s2[h2]);
while(now > m)
{
now -= abs(s1[q1]-s2[q2]);
++q1, ++q2;
}
ans = max(h1-q1+1, ans);
++h1, ++h2;
}
if(len1-k == len2-1)
{
s1[len1] = s2[len2-1];
++len1, --len2;
s1[len1] = s2[len2] = '\0';
}
if(ans >= len2) break;
}
}
int main()
{
scanf("%d", &t);
while(t--)
{
ans = 0;
scanf("%d %s", &m, s);
mlen = strlen(s);
work();
reverse(s, s+mlen);
work();
printf("%d\n", ans);
}
return 0;
}
继续加油~