您的位置:首页 > 其它

HDU 6103 Kirinriki(尺取)

2017-09-09 14:28 405 查看
Description

定义两个长度均为n的字符串A和B的距离为disA,B=∑i=0n−1|Ai−Bn−1−i|,给出一个字符串S,问S的满足距离小于m的两个等长不相交子串的长度最大值

Input

第一行一整数T表示用例组数,每组用例首先输入一整数m表示对S的子串距离的限制,之后输入一个只有小写字母的字符串S(T≤100,0≤m≤5000,2≤|S|≤5000,∑|S|≤20000)

Output

输出S的满足距离小于m的两个等长不相交子串的长度最大值

Sample Input

1

5

abcdefedcb

Sample Output

5

Solution

设两个子串分别是S[x,x+len]和S[y,y+len],其中y>x+len ,那么这两个字符串的距离为∑i+j=x+y+len|Si−Sj|,枚举i+j的和k,得到序列|Si−Sj|,i+j=k,问题变成求这个序列中满足和不超过m的最长子段,尺取法即可,总时间复杂度O(n2)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
namespace fastIO
{
#define BUF_SIZE 100000
//fread -> read
bool IOerror=0;
inline char nc()
{
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend)
{
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1)
{
IOerror=1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch)
{
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}
inline void read(int &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');
}
inline void readc(char &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
x=ch;
}
inline void reads(char *x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
int n=0;
while(1)
{
x[n++]=ch;
if(blank(ch=nc()))break;
}
x
='\0';
}
#undef BUF_SIZE
};
using namespace fastIO;
const int maxn=5005;
int T,m,a[maxn];
char s[maxn];
int deal(int *a,int n)
{
int l=0,r=0,sum=0,ans=0;
while(l<n)
{
while(r<n&&sum+a[r]<=m)sum+=a[r++];
ans=max(ans,r-l);
sum-=a[l++];
}
return ans;
}
int main()
{
read(T);
//scanf("%d",&T);
while(T--)
{
//scanf("%d",&m);
//scanf("%s",s+1);
read(m);reads(s+1);
int n=strlen(s+1),ans=0;
for(int i=2;i<=2*n;i++)
{
int res=0;
for(int j=1;j<=(i-1)/2;j++)
{
int k=i-j;
if(k<=n)a[res++]=abs(s[j]-s[k]);
}
ans=max(ans,deal(a,res));
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: