descripción
Dada una cadena s y una cadena no vacía p, busque todas las subcadenas de la letra dislexia de p en s, y devuelva el índice inicial de estas subcadenas.
La cadena contiene solo letras minúsculas en inglés, y la longitud de las cadenas s y p no son más de 20100.
Descripción:
Las palabras alifáticas se refieren a cadenas con las mismas letras pero con diferentes disposiciones.
No se considera el orden en que se emiten las respuestas.
Ejemplo 1:
Entrada:
s: "cbaebabacd" p: "abc"
Salida:
[0, 6]
Explicación:
La subcadena cuyo índice inicial es igual a 0 es "cba", que es un anagrama de "abc".
La subcadena cuyo índice inicial es igual a 6 es "bac", que es un anagrama de "abc".
Ejemplo 2:
输入:
s: "abab" p: "ab"
Salida:
[0, 1, 2]
Explicación:
La subcadena cuyo índice inicial es igual a 0 es "ab", que es un anagrama de "ab".
La subcadena cuyo índice inicial es igual a 1 es "ba", que es un anagrama de "ab".
La subcadena cuyo índice inicial es igual a 2 es "ab", que es un anagrama de "ab".
Fuente:
Enlace de LeetCode : https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
Resolver
class Solution {
public:
// 方法一,暴力解法,以每个字符起点开始判断, 时间复杂度O(m * n),需要额外的空间复杂度
// 低效率通过, 1300ms
vector<int> findAnagrams_1e(string s, string p) {
const int n = s.size();
const int m = p.size();
vector<int> res;
for (int i = 0; i <= n - m; ++i) {
if (isAnagrams(p, s, i, i + m)) {
res.emplace_back(i);
}
}
return res;
}
// 方法二,暴力解法优化,以每个字符起点开始判断, 时间复杂度O(m * n),需要额外的空间复杂度
// 低效率通过, 850ms
vector<int> findAnagrams_2e(string s, string p) {
const int n = s.size();
const int m = p.size();
vector<int> res;
bool preIsAnagrams = false;
for (int i = 0; i <= n - m; ++i) {
if (preIsAnagrams && s[i - 1] == s[i + m - 1]) {
// 如果发现前一个满足条件,即s[i-1....i-1+m)符合条件
// 则只需要判断s[i-1] 是否等于 s[i+m-1],即递增中去掉的那个字符和新加入的字符是否一致,一致则同样满足条件
res.emplace_back(i);
preIsAnagrams = true;
continue;
}
if (isAnagrams(p, s, i, i + m)) {
res.emplace_back(i);
preIsAnagrams = true;
continue;
}
preIsAnagrams = false;
}
return res;
}
// 方法三,双指针滑动窗口
vector<int> findAnagrams(string s, string p) {
const int n = s.size();
const int m = p.size();
int record[126]{0};
for (char &c : p) {
++record[c];
}
int l = 0, r = 0, num = 0;
vector<int> res;
while (r < n) {
if (record[s[r]] > 0) {
++num;
}
--record[s[r]];
++r;
while (num == m) {
if (r - l == m) {
res.emplace_back(l);
}
if (record[s[l]] == 0) {
--num;
}
++record[s[l]];
++l;
}
}
return res;
}
private:
/*!
*
* @param p 被匹配字符串
* @param s 待匹配字符串
* @param is 起点,相当于begin
* @param ie 终点, 相等于end
* @return 返回是否是异位匹配
*/
bool isAnagrams(const std::string_view p, const std::string_view s, int is, int ie) {
int pattern[26]{0};
for (const auto &c : p) {
++pattern[c - 'a'];
}
for (int i = is; i < ie; ++i) {
--pattern[s[i] - 'a'];
}
for (const int &num : pattern) {
if (num != 0) {
return false;
}
}
return true;
}
};