首页 > 代码库 > HDU 6103 Kirinriki 枚举长度 尺取法
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; }
思考: 以前看过尺取法, 忘了......以后记住求连续区间不超过某一个上限或者不低于某个下限的长度应该用尺取法
HDU 6103 Kirinriki 枚举长度 尺取法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。