HDU 6103 Kirinriki 枚举长度 尺取法

  题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6103

  题目描述: 定义两个相同长度的字符串的值为首尾开始字符串的ASCII相减, 求一个字符串中任取两个相同长度的不重叠的值不超过m的最大长度

  解题思路: 求连续区间不超过某一个上限或者不低于某个下限的应该用尺取法 ,复杂度为O(n),  本题n是5000所以O(n^2)可行, 枚举前缀和后缀(通过枚举前缀, 再将字符串翻转枚举前缀进行), 再进行尺取

  代码:  代码中有注释

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <cstring>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <stack>
#include <deque>

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;

const int maxn = 21000;
char str[maxn];
int m,len;

int solve() {
    int ans = 0;
//    cout << len << endl;
    for( int i = len; i >= 1; i-- ) { // 枚举每一个前缀
//        cout << "--- " << endl;
        int cnt = i/2-1;
        int  d = 0,t = 0,p = 0;
        for( int j = 0 ; j <= cnt; j++ ) {
            d += abs( str[1+j]-str[i-j] ); // 加上权值
            if( d > m ) {
                d -= abs( str[1+p]-str[i-p] ); // 将最前面的剪掉, 将最后面剪掉, 这样下一次循环还会加的是最后面
                d -= abs( str[1+j]-str[i-j] );
                p++; // 记录第一个字符串最前面的指针
                t--; // 记录单个字符串的长度
                j--; // 记录第一个字符串最后面的指针
            }
            else {
                t++; // d <= m 就是说还可以向后再加一个字符串长度可以加一
                ans=max(ans,t);
            }
        }
    }
    return ans;
}

int main() {
    int T;
    scanf( "%d", &T );
    while( T-- ){
        int ans = 0;
        scanf( "%d%s", &m, str+1 );
        len = (int)strlen(str+1);
        ans = max( ans, solve() );
        reverse( str+1, str+len+1 ); // 后缀和
        ans = max( ans, solve() );
//        reverse( str+1, str+len+1 );
        printf("%d\n",ans);
    }
    return 0;
}

  思考: 以前看过尺取法, 忘了......以后记住求连续区间不超过某一个上限或者不低于某个下限的长度应该用尺取法 

时间: 2024-10-12 17:45:34

HDU 6103 Kirinriki 枚举长度 尺取法的相关文章

HDU 6103 Kirinriki(尺取法)

http://acm.hdu.edu.cn/showproblem.php?pid=6103 题意: 给出一个字符串,在其中找两串互不重叠的子串,计算它们之间的dis值,要求dis值小于等于m,求能选的子串的最大长度. 思路: 由于这两个子串是互不重叠的,那么这两个子串之间的间隔可以是奇数也可以是偶数,针对这两种情况我们枚举中心点,然后尺取法处理,具体看代码就懂了. 1 #include<iostream> 2 #include<algorithm> 3 #include<c

HDU 5358 First One 数学+尺取法

多校的题,摆明了数学题,但是没想出来,蠢爆了,之前算了半天的s[i][j]的和,其实是积.其实比赛的时候我连log(s[i][j])+1是s[i][j]的位数都没看出来,说出来都丢人. 知道了这个之后,就枚举二进制数的每一位,因为元素都是非负数,所以sum数组是非降的,这里用到了尺取法,之前也是听说过,应该是做过吧,不太记得了. 因为[2k-1,2k)的位数是k,枚举时,固定左端点,在sum数组找到最小的大于等于2k-1,最大的小于2k的点,这中间的点和左端点的s[i][j]就对于当前的k满足条

HDU 6103 Kirinriki (思维 双指针)

Kirinriki Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2169    Accepted Submission(s): 879 Problem Description We define the distance of two strings A and B with same length n isdisA,B=∑i=0n−

hdu 6103 Kirinriki

题意:给出字符串s,以及m,计算距离字符串距离:dis(A,B)=∑|Ai?B|n?1?i|,在距离小于等于m的条件下找到最长的子串,并输出长度. 题解:官方题解就很好啊,从中心点向两边扩展,,如果合法,外层指针继续扩展,如果不合法,内层指针向外扩展.枚举一下中心向外延伸. 第一次是找到实质的中心点,依次扩展(存在中心点和邻接中心点的位置比较不到的问题),第二次是比较中心点和邻近中心点的位置. #include <stdio.h> #include <algorithm> #inc

Hdu 5510 Bazinga(KMP+尺取法)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=5510 思路:设两个指针l.r,对于字符串a.b.c,若a为b的子串则下次比较时可直接比较b,c.枚举r,依次比较s[l]--s[r-1]是否为s[r]的子串,若s[i]为s[r]的子串,则l++.否则答案更新为r. #include<cstdio> #include<cstring> #include<iostream> #include<algorith

HDU 5328 Problem Killer(尺取法)

You are a "Problem Killer", you want to solve many problems. Now you have nn problems, the ii-th problem's difficulty is represented by an integer aiai (1≤ai≤1091≤ai≤109). For some strange reason, you must choose some integer ll and rr (1≤l≤r≤n1

hdu 4737 A Bit Fun 尺取法

A Bit Fun Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description There are n numbers in a array, as a0, a1 ... , an-1, and another number m. We define a function f(i, j) = ai|ai+1|ai+2| ... | aj . Wher

【尺取法】【转】

尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案.之所以需要掌握这个技巧,是因为尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的 使用尺取法时应清楚以下四点: 1.  什么情况下能使用尺取法?  2.何时推进区间的端点? 3.如何推进区间的端点? 3.何时结束区间的枚举? 尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行

hdu 5371 Hotaru&#39;s problem(manacher+尺取法)

题意: 给定一个有n个数字的序列,找出一个连续的子序列满足这样的条件: 1. 平均分成三段 2. 第一段与第三段一样 3. 第二段是第一段的倒序.求这样的子序列的最大长度. 数据范围:n~100000 解析: 我看网络上面很多的题解都是用O(n2/32)的做法水数据过去的,这种做法是先用mancher算法预处理出每个每个回文串最远所能抵达的位置,然后枚举每个位置i,再枚举其回文串的长度,然后枚举当前位置i到回文串所能抵达的最远距离,判断途径的位置j是,否有回文串能够到当前位置i.但是这种做法的复