codeforces 1187B 菜鸟题解
题目链接:https://codeforc.es/problemset/problem/1187/B
题目解释:
输入:n,长度为n的字符串, m,m次查询
给定一个字符串str,然后给m次查询,每次查询给一个字符串ask,判断ask的所有字符串在str字符串中出现的位置由前到后最大的。
说人话,
举个栗子:str = abcde, ask = abd,那么最后的结果就为4;
举个栗子:str = abacd, ask = aab,那么最后的结果就为3,因为有两个a,第二个a出现位置最远,所以就是3
最后一个栗子:str = abcade, ask = acae,最后结果就为6,最后一个e出现第六位。
题目捋清楚了,然后想一想题目给的条件,保证str和ask都为小写字母,小写字母总共26个,emm……
大概有点思路了
分析
因为在ask中出现多次同一个字符的话,要在str中找到相对应字符多次出现的位置,所以可以搞一个数组分别存储26个字母出现的位置,vector< int > v[26],这个数组用来存储每一个字母出现的位置,不是下标。
这个问题解决了
第二个问题,查询呢,也就是所有字母里面下标的从头到尾出现次序的最大值,
还是str = abcade, ask = acae,
那么vector[‘a’ - ‘a’] = {1, 4}, vector[‘c’ - ‘a’] = {3}, vector[‘e’ - ‘a’] = 6
用ans来记录答案,遍历ask数组
1.a ans = max(ans, vector[‘a’][0]) = 1
2.c ans = max(ans, vector[‘c’][0]) = 3
3.a ans = max(ans, vector[‘a’][1]) = 4
4.e ans = max(ans, vector[‘e’][0]) = 6
通过上面的手动计算,也就明了了
我们除了需要一个vector来记录每个字母出现的下标,还要记录当前这个字母遍历了几次,也就是当前字母在vector中遍历到哪个下标了
所以新建一个ind[26]的数组,初始化为0,在上面的例子中,ind的变化情况:
1.变换前:ind[‘a’] = 0,变化后: index[‘a’] = 1, ans = 1
2.变换前:ind[‘c’] = 0,变化后: index[‘c’] = 1, ans = 3
3.变换前:ind[‘a’] = 1,变化后: index[‘a’] = 2, ans = 4
4.变换前:ind[‘e’] = 0,变化后: index[‘e’] = 1, ans = 6
到这里思路明确了,代码也就出来了
上代码
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 26;
vector<int> v[N];
int main(){
ios::sync_with_stdio(false);
int n, m;
string str;
cin >> n >> str;
for (int i = 0; i < n; i++) v[str[i] - 'a'].push_back(i + 1);
cin >> m;
while (m--){
int ind[N] = {0};
string ask;
cin >> ask;
int ans = 0;
for (int i = 0; i < ask.length(); i++){
ans = max(ans, v[ask[i] - 'a'][ind[ask[i] - 'a']++]);
}
cout << ans << endl;
}
return 0;
}
我第一次,为什么想要用set做,脑瘫菜鸟的日常,难受QAQ
有志者,事竟成,破釜沉舟,百二秦关终属楚。
苦心人,天不负,卧薪尝胆,三千越甲可吞吴。