Kirinriki

Kirinriki

定义两个长度相等的字符串\(\{a_i\},\{b_i\}\)的距离为\(\sum_{i=1}^n|a_i-b_{n-i+1}|\)(其中n为字符串的长度),给出一个字符串\(\{s_i\}\),寻找其中两个长度相等连续的不相交的子串,让两个子串的长度不超过m的情况下,长度的最大值,\(n\leq 5000\)

显然两个串的距离的计算类似回文子串,而两个子串显然会关于一个点对称,由于这个点不一定落在一个字符上,于是我们将字符的所有间隔都加上\('#'\),然后我们只要在字符上枚举这个中间点,然后把两个子串相对于中间点的外沿向两边尽量扩展,因为距离是随着长度单调递增的,如果发现距离扩展的超过m,就将内沿向外扩展,然后随便记录最大的长度,就可以做到\(O(n^2)\)了。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define Size 5050
using namespace std;
char s[Size],s1[Size*2];
int main(){
    int lsy,m,sl,sl1;scanf("%d",&lsy);
    while(lsy--){
        sl1=0,scanf("%d%s",&m,s+1),sl=strlen(s+1);
        for(int i(1);i<=sl;++i)
            s1[++sl1]='#',s1[++sl1]=s[i];
        s1[++sl1]='#';int ans(0);
        for(int i(1),j,k,sum,tot;i<=sl1;++i){
            j=i+1,sum=tot=0;
            for(k=i+1;k<=sl1&&2*i-k>0;++k){
                sum+=abs(s1[k]-s1[2*i-k]),tot+=s1[k]!='#';
                while(sum>m)
                    sum-=abs(s1[j]-s1[2*i-j]),
                        tot-=s1[j]!='#',++j;
                ans=max(ans,tot);
            }
        }printf("%d\n",ans);
    }return 0;
}

转载于:https://www.cnblogs.com/a1b3c7d9/p/11408683.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值