说在前面
🎈每天进行一道算法题目练习,今天的题目是“环绕字符串中唯一的子字符串”。
问题描述
把字符串 s 看作是 “abcdefghijklmnopqrstuvwxyz” 的无限环绕字符串,所以 s 看起来是这样的:\
"...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd...." .
现在给定另一个字符串 p 。返回 s 中 唯一 的 p 的 非空子串 的数量 。 \
示例 1:
输入: p = "a"
输出: 1
解释: 字符串 s 中只有一个"a"子字符。
示例 2:
输入: p = "cac"
输出: 2
解释: 字符串 s 中的字符串“cac”只有两个子串“a”、“c”。.
示例 3:
输入: p = "zab"
输出: 6
解释: 在字符串 s 中有六个子串“z”、“a”、“b”、“za”、“ab”、“zab”。
提示:
1 <= p.length <= 10^5
p 由小写英文字母构成
思路分析
题目的意思是我们要在无限环绕字符串s中找到输入参数p的子串数量。\
如:p = "zab"时,在字符串 s 中有六个子串“z”、“a”、“b”、“za”、“ab”、“zab”。\
题目要求不同的子串个数,那么对于两个以同一个字符结尾的子串,长的那个子串必然包含短的那个。例如abcd,bcd 均以 d 结尾bcd 是 abcd 的子串。知道了最长长度,也就知道了不同的子串的个数,所以我们只需要记录每一个字符结尾的子串最大长度,最后将所有字符结尾的子串长度相加即可得到我们想要的答案。\
因为s是无限环绕字符串,所以字符'z'的下一个字符应该是'a','a'的上一个字符应该是'z',我们可以这样来判断两个字符是否是相邻字符:(p[i].charCodeAt() - p[i - 1].charCodeAt() + 26) % 26 == 1,两字符相邻则说明它们可以构成一串子串,否则则说明当前字符需单独成串,具体代码如下:
AC代码
/**
* @param {string} p
* @return {number}
*/
var findSubstringInWraproundString = function(p) {
const dp = new Array(26).fill(0);
let num = 0;
for(let i = 0; i < p.length; i++){
i > 0 && (p[i].charCodeAt() - p[i - 1].charCodeAt() + 26) % 26 == 1 ? num++ : num = 1;
const ind = p[i].charCodeAt() - 97;
dp[ind] = Math.max(dp[ind],num);
}
return dp.reduce((a,b)=>a+b);
};
说在后面
🎉这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。