找出数组中的美丽下标 II(KMP,二分\双指针)
https://leetcode.cn/problems/find-beautiful-indices-in-the-given-array-ii/description/
给你一个下标从 \(0\) 开始的字符串\(s\) 、字符串 \(a\) 、字符串 \(b\) 和一个整数 \(k\) 。
如果下标 \(i\) 满足以下条件,则认为它是一个 美丽下标 :
- \(0 <= i <= s.length - a.length\)
- \(s[i..(i + a.length - 1)] == a\)
- 存在下标\(j\)使得:
- \(0 <= j <= s.length - b.length\)
- \(s[j..(j + b.length - 1)] == b\)
- \(|j - i| <= k\)
以数组形式按 从小到大排序 返回美丽下标。
示例 1:
输入:s = "isawsquirrelnearmysquirrelhouseohmy", a = "my", b = "squirrel", k = 15
输出:[16,33]
解释:存在 2 个美丽下标:[16,33]。
- 下标 16 是美丽下标,因为 s[16..17] == "my" ,且存在下标 4 ,满足 s[4..11] == "squirrel" 且 |16 - 4| <= 15 。
- 下标 33 是美丽下标,因为 s[33..34] == "my" ,且存在下标 18 ,满足 s[18..25] == "squirrel" 且 |33 - 18| <= 15 。
因此返回 [16,33] 作为结果。
示例 2:
输入:s = "abcd", a = "a", b = "a", k = 4
输出:[0]
解释:存在 1 个美丽下标:[0]。
- 下标 0 是美丽下标,因为 s[0..0] == "a" ,且存在下标 0 ,满足 s[0..0] == "a" 且 |0 - 0| <= 4 。
因此返回 [0] 作为结果。
提示:
\(1 <= k <= s.length <= 5 * 10^5\)
\(1 <= a.length, b.length <= 5 * 10^5\)
$s、a、和 b $只包含小写英文字母。
这个题就是kmp+二分,用kmp先把两个数组a,b在s中的位置处理出来
class Solution {
public:
int nxt[500500];
void GetNext(string s){
nxt[0]=-1;
int k=-1;
int j=0;
int m=s.size();
while(j<m-1){
if(k==-1||s[j]==s[k]){
++j;
++k;
nxt[j]=k;
}
else{
k=nxt[k];
}
}
}
vector<int> kmp(string a,string b){
int i=0;
int j=0;
int tot=0;
vector<int> v;
int n=a.size(),m=b.size();
while(i<n){
if(j==-1||a[i]==b[j]){
i++;j++;
}
else{
j=nxt[j];
}
if(j==m){
i--;j--;
v.push_back(i-m+1);
j=nxt[j];
}
}
return v;
}
vector<int> beautifulIndices(string s, string a, string b, int k) {
GetNext(s);
vector<int>pos_a;
vector<int>pos_b;
pos_a=kmp(s,a);
pos_b=kmp(s,b);
int n = pos_a.size(), m = pos_b.size();
vector<int>ans;
for(int i = 0; i < pos_a.size(); i++){
int idx = lower_bound(pos_b.begin(), pos_b.end(), pos_a[i]) - pos_b.begin();
if((idx < m && abs(pos_b[idx] - pos_a[i]) <= k) || (idx - 1 >= 0 && abs(pos_b[idx - 1] - pos_a[i]) <= k)){
ans.push_back(pos_a[i]);
}
}
return ans;
}
};