题解 | 月月查华华的手机

月月查华华的手机

https://www.nowcoder.com/practice/c2877187b1bb4573927e759a60f5d3e1

蒟蒻的我只想得到二分查找每一个字母,但好像没人发使用upper_bound()的版本,遂发出()

思路:对于华华的昵称字符串A,我们可以预处理每个字母出现的位置,即用一个二维数组a[26][],其中a[i]按升序存储某个字母在字符串A中出现的所有位置

对于每个推荐好友的昵称字符串B,我们按顺序遍历B的每个字符,并在A中查找该字符出现的位置,当我们匹配B的第i个字符时,需要在A中找到大于前一个字符匹配位置的该字符最早出现的位置,这样就可以保证B是A的一个子序列

具体做法:

1. 用last_idx记录在A中已匹配的最后一个位置,初始化为-1

2. 对于B中的每个字符:

-获取该字符对应的字母索引

-在a[索引]这个有序数组中,用二分查找找到第一个大于last_idx的位置

-如果找不到,说明B不是A的子序列,输出"No"

-如果找到,更新last_idx为该位置

3. 如果B的所有字符都能在A中找到这样的位置,则输出"Yes"

这种方法的时间复杂度为:

-预处理:O(|A|),其中|A|是字符串A的长度

-每次查询:O(|B| * log|A|),其中|B|是查询字符串的长度

-总复杂度为O(|A| + N * |B| * log|A|),能过

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    string s;
    cin>>s;
    int len=s.length();
    vector<vector<int>> a(26,vector<int>(0));
    for(int i=0;i<len;i++){
        a[s[i]-'a'].push_back(i);
    }
    int q;
    cin>>q;
    while(q--){
        cin>>s;
        len=s.length();
        int last_idx=-1;
        int f=1;
        for(int i=0;i<len;i++){
            int idx=s[i]-'a';
            auto it=upper_bound(a[idx].begin(),a[idx].end(),last_idx);
            if(it==a[idx].end()){
                f=0;
                break;
            }
            else {
                last_idx=*it;
            }
        }
        if(f) cout<<"Yes\n";
        else cout<<"No\n";
    }
}
全部评论

相关推荐

程序员小白条:三方不签,不就是纯实习骗人吗,还是小公司,没毛了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务