我的理解:删掉字符串中的MT子序列
但是不是,比如例题,删去之后会有两端字符,要选取其中最长的一段字符。
题目解析:给定一个字符串,该字符串 = 前缀字符串 + 字符串 + 后缀字符串
前缀字符串以T结尾,且有MT这一个子序列
后缀字符串也是以MT开头,且以T结尾
最后掐头去尾剩中间,中间就是我们想要的答案
具体做法,找到M后最近的一个T字母
我的疑惑:题目中有两段字符串拼接在一起,这个应该如何处理?
目前想到的解决方法,用一个存储最终的结果,用一个存储当前的子串,一旦遇到结尾的T就进行长度比较,留下长度较长的那一个
以上疑惑是因为我理解错了题目含义
// 二分查找
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
std::vector<int> vm;
//record the index of m
std::vector<int> vt;
//record the index of t
char str[100050];
//get the string
int main() {
int len;
scanf("%d %s", &len, str);
// 记录 'M' 和 'T' 的下标
for (int i = 0; i < len; i++) {
if (str[i] == 'M') {
vm.push_back(i);
} else if (str[i] == 'T') {
vt.push_back(i);
}
}
// 查找第一个 'M' 后面的 'T'
auto st_ptr = std::upper_bound(vt.begin(), vt.end(), *vm.begin());
// 查找最后一个 'T' 前面的 'M'
//upper_bound(begin(),end(),num)
//在[begin,start]中寻找第一个比num大的数字
auto ed_ptr = std::upper_bound(vm.begin(), vm.end(), *vt.rbegin());
// 下标校准
int st = (*st_ptr) + 1, ed = *(--ed_ptr) - st;
// 构造答案字符串,st -> 起点,ed -> 长度
std::string res{ str, st, ed };
printf("%s", res.c_str());
return 0;
}
作者:detachmliu
链接:https://leetcode-cn.com/problems/z3XKBp/solution/kao-yue-du-li-jie-de-tan-xin-ti-oo-by-de-uycf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
补充知识1:
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
一个疑问:
对迭代器尾部指针解引用不是未定义的吗?怎么会输出0呢?