题目链接
先上AC代码。
参开代码:
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;string s[100005];
unordered_map<string, int> m;
bool check(string a, string b)
{if (a.size() < b.size()) return false;for (int i = 0; i < b.size();i++)if (a[i] != b[i]) return false;return true;
}int main()
{ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);int w, n;cin >> w >> n;for (int i = 0; i < w; i++){cin >> s[i];m[s[i]] = i + 1;}sort(s, s + w);string str;int num;for (int i = 0; i < n; i++){cin >> num >> str;int l = 0, r = w;int mid = (l + r) >> 1;while (l <= r){if (s[mid] >= str) r = mid - 1;else l = mid + 1;mid = (l + r) >> 1;}if (s[mid + num].substr(0, str.size()) == str) cout << m[s[mid + num]] << endl;else cout << -1 << endl;}return 0;
}
思路:
基本思路是先对字典中的字符串sort排序,然后使用查找的方法确定找到的字符串开始计算的第n个字符串是否与待自动补全的字符串匹配,若存在,输出第n个字符串的初始顺序;若不存在,则输出-1。
而对于查找,若使用暴力方法,则会导致查找超时。当查找超时时,我们不难想到可以用时间复杂度为logn的二分查找,代码如下所示:
while (l <= r){if (s[mid] >= str) r = mid - 1;else l = mid + 1;mid = (l + r) >> 1;}
上面是基础的二分查找写法,起初我对第三行的大于等于并不理解,写成了大于,导致我只过了少部分测试店。后来回想,发现:若是大于号,当字典中有和待匹配字符串相同的字符串,则会导致查找的字符串并不是满足条件的第一个字符串。又因为题目说字典中的字符串不可能相同,因此大于等于号查找出来的字符串一定是当前字典序中第一个符合条件的字符串。