【排序二分查找】自动完成 APP

知识点学习

一:定义pair<string,int>类型变量,存入vector数组中,可以根据pair类型变量的第一个位置的数据直接排序

二:关于lower_bound()函数和upper_bound()函数

       学习博客:https://blog.csdn.net/qq_40160605/article/details/80150252

        作用是利用二分查找方法对一个有序的数组进行查找

        若数组是从小到大排序,可利用下面两种方法二分查找:

        lower_bound(begin,end,num)   数组从begin到end中查找一个大于或等于num的值 ,并返回该值的地址,并通过返回的地址减去数组的首地址即可找到对应值的下标;        若找不到则返回end

         upper_bound(begin,end,num)   数组从begin到end中查找一个大于num的值,并返回该值的地址,并通过返回的地址减去数组的首地址即可找到对应值的下标;               若找不到则返回end       

 

        若数组是从大到小排序,可对函数进行重载

        lower_bound(begin,end,num,greater<type>())           

        upper_bound(begin,end,num,greater<type>())      原理同上 

三:make_pair()函数

生成一个pair对象,用处很多,可以用于这道题中把两个变量添加到vector数组中, 也可以对函数为pair类型传参时可以用到make_pair()

四:substr()函数

s.substr(begin,size)表示对s字符串,从begin下标开始,长度为size大小的字符串

 

 


问题 E: 自动完成 APP

时间限制: 1 Sec  内存限制: 256 MB
提交: 236  解决: 63
[提交] [状态] [命题人:admin]

题目描述

题目描述

奶牛 Bessie 很喜欢用手机上网聊天,但她的蹄子太大,经常会按到好几个键造成不必要的麻烦(丢死人了,你下辈子还是不要当奶牛了)。于是 Farmer John 给她专门设计了一套「自动完成 APP」。这个 APP 能够连接到在线词典来获取词库(词库的来源是 Bessie 常用的 n 个单词),并且有着自动补全的功能。当 Bessie 想打出她的一个常用单词时,她只需输入这个单词的某个前缀,并询问词库中拥有这个前缀的字典序第 k 小的单词,APP 就会返回这是词库中的第几个单词。
Farmer John 是个大忙人,所以编写 APP 的任务自然就交给了你。

 

输入

第一行两个整数 n,m,表示词库的单词个数和 Bessie 的询问次数。
接下来 n 行,每行一个字符串,表示 Bessie 的常用单词,输入的第 i 个字符串在词库中编号为 i。
接下来 m 行,每行一个整数 k 和一个字符串 S,表示 Bessie 的询问,意义是询问词库中以 S 为前缀的字典序第 k 小的单词在词库中的编号。

 

输出

对于每次询问输出一个整数,表示以S为前缀的字典序第 k 小的单词在词库中的编号;如果不存在这样的单词,输出 −1。

 

样例输入

复制样例数据

10 3
dab
ba
ab
daa
aa
aaa
aab
abc
ac
dadba
4 a
2 da
4 da

样例输出

3
1
-1

 

提示

(1) 以 a 为前缀的单词有 {aa,aaa,aab,ab,abc,ac},其中字典序第 4 小的是 ab,是词库的第 3 个单词。
(2) 以 da 为前缀的单词有 {daa,dab,dadba},其中字典序第 2 小的是 dab,是词库的第 1 个单词;没有第 4 小的单词。

对于 20% 的数据,1≤ 词库的字母总量,询问的字母总量 ≤103。
对于 100%的数据,1≤ 词库的字母总量,询问的字母总量 ≤106,保证词库里的单词两两不同,所有字符串只包含小写字母。

 


题意:

      给定n,表示词库中存在n个单词,每次询问一个字符串s和数字k,表示要找到一个以以字符串s 为前缀的第k小的字符串,并输出该字符串的最初下标

题解:

        用pair存储字符串和对应的编号,并存入vector数组中

        对vector数组排序,注意pair的第一个位置存字符串,第二个位置存编号,因为排序的时候第一个位置的优先级高,可以直接根据字典序排序

         用户lower_bound函数进行二分查找,返回对应位置的编号,判断即可

 


 

代码

#include<bits/stdc++.h>
typedef long long ll;
const int mod=1000000007;
const int N=9;
using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<string,int> psi;
vector<psi> vec;
ll n,m;
char str[5000007];
int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);cout.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;++i)
    {
        cin>>str;
        vec.push_back(make_pair(str,i));
    }
    //for(int i=0;i<n;i++);
    sort(vec.begin(),vec.end());
    for(int i=0;i<m;++i)
    {
        int k;
        scanf("%d%s",&k,str);
        string stmp=str;
        int slen=lower_bound(vec.begin(),vec.end(),make_pair(stmp,0))-vec.begin();
        if(slen+k-1<vec.size()&&(vec[slen+k-1].first.size()>=stmp.size())&&vec[slen+k-1].first.substr(0,stmp.size())==stmp)
            printf("%d\n",vec[slen+k-1].second+1);
        else
            printf("-1\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值