算法初探LeetCode-环绕字符串中唯一的子字符串

119 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

LeetCode467:环绕字符串中唯一的子字符串

把字符串 s 看作 abcdefghijklmnopqrstuvwxyz 的无限环绕字符串,所以 s 看起来是这样的:zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd  现在给定另一个字符串 p 。返回 s 中 不同 的 p 的 非空子串 的数量 

示例 1:

输入: p = "a"
输出: 1
解释: 字符串 s 中只有 p 的一个 "a" 子字符。

示例 2:

输入: p = "cac"
输出: 2
解释: 字符串 s 中只有 p 的两个子串 ("a", "c") 。

示例 3:

输入: p = "zab"
输出: 6
解释: 在字符串 s 中有 p 的六个子串 ("z", "a", "b", "za", "ab", "zab") 。

提示:

  • 1<=p.length<=1051 <= p.length <= 10^5
  • p 由小写英文字母组成

思路分析

根据题意来分析统计以26个字母中每一个字母结尾的连续子串的最大长度,这个长度也对应的和这个子串的中以对应这个字母结尾的子串的个数

举例、假设我们通过遍历发现了一个连续子串abcd,那么对应的以字母d为结束的子串有 abcd、bcd、cd、d一共4个,等于当前这个子串的长度 如果后面再继续遍历,发现了一个更长的以字母d为结束的子串yzabcd,那么同理以字母d为结束的子串的个数更新为当前字符串的长度6

如果遍历过程中发现了一个新的子串cde,对应的是以字母e结尾的子串cde、de、e,和之前统计到的d结尾的子串的个数并无冲突关联

算法代码

public int findSubstringInWraproundString(String p) {
    int[] dp = new int[26];
    char pre_c = p.charAt(0);
    int n = 1;
    dp[pre_c - 'a'] = 1;
    for (int i = 1; i < p.length(); i++) {
        char c = p.charAt(i);
        if ((c - pre_c + 26) % 26 == 1) {
            n++;
        } else {
            n = 1;
        }
        dp[c - 'a'] = Math.max(dp[c - 'a'], n);
        pre_c = c;
    }
    int ans = 0;
    for (int i: dp) {
        ans += i;
    }
    return ans;
}

结果详情

Snipaste_2023-02-07_23-22-11.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!