LeetCode-438. Encuentra todas las palabras disfóricas de letras en una cadena

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;
        }
    };

 

Supongo que te gusta

Origin blog.csdn.net/u010323563/article/details/112920002
Recomendado
Clasificación