• Kirinriki


    HDU

    题意:给定一个长度不超过5000的字符串s,求它的两个不重叠的长度都为(n)的连续子串(s1,s2),使得(dis(s1,s2)<=m).对于两个字符串(A,B),定义它们的距离(dis=sum_{i=1}^nabs(A_i-B_{n+1-i})).

    分析:借鉴于马拉车算法的思想,我们把字符串S每个的字符之间插上一个隔板'|',便于我们不需要再讨论串的奇偶性.然后因为两个子串(s1,s2)是不重叠的,所以这两个子串肯定存在一个对称中心(要么是字母,要么是隔板),所以我们直接枚举这个对称中心,然后用尺取法,一点一点向外扩展,得到最大长度.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=5005;
    char ch[N],s[N*2];
    int main(){
    	int T;scanf("%d",&T);
    	while(T--){
    		int m;scanf("%d%s",&m,ch+1);
    		int tot=strlen(ch+1),n=0;s[++n]='|';//第一个字符是隔板
    		for(int i=1;i<=tot;++i)
    			s[++n]=ch[i],s[++n]='|';//每读入一个字符,加一个隔板
    		int ans=0;
    		for(int i=1;i<=n;++i){
    			int l=0,r=0,now=0,x=i-1,y=i+1;
    			while(x-r>=1&&y+r<=n){//不越界
    				if(now+abs(s[x-r]-s[y+r])<=m){//能够向外扩展r就扩展r
    					ans=max(ans,(r-l+1)/2);//更新答案
    					now+=abs(s[x-r]-s[y+r]);
    					++r;
    				}
    				else{
    					now-=abs(s[x-l]-s[y+l]);//不能扩展r,就缩进l,保证能够扩展r
    					++l;
    				}
    			}
    		}
    		printf("%d
    ",ans);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    你看,那个人好像一条狗哎
    我竟然被抓去做了比特币挖矿工
    聊聊JAVA中 String类为什么不可变
    三分钟深入TT猫之故障转移
    shell实现两个数的相加
    shell截取字符串的方法
    Vi命令:如何删除全部内容?
    bash中不可以用字符串做数组下标
    awk打印出当前行的上一行
    awk同时处理多个文件
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11427868.html
Copyright © 2020-2023  润新知