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

106 阅读1分钟

🍀环绕字符串中唯一的子字符串

描述:

 # 把字符串 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 <= 105
 p 由小写英文字母组成

思考:

已知目标字符串是abc..z环绕的字符串,求p在里面与之对应的子串的数,又因为s串是连续的,因此只用求p中连续子串的数目,也就是求前一个字母和后一个字母的关系,这就能立刻想到动态规划方法,判断两个字母是不是连续的,可以用后一个减去前一个是否等于1,是则是连续的,否则不是,(p[i-1]+1)%26 == p[i]%26,两边对26取模看是否相等。

实现:

 class Solution {
     public int findSubstringInWraproundString(String p) {
         int[] dp = new int[26];
         int count = 0;
         for (int i = 0; i < p.length(); ++i) {
             if (i > 0 && (p.charAt(i) - p.charAt(i - 1) + 26) % 26 == 1) { // 字符之差为 1 或 -25
                 ++count;
             } else {
                 count = 1;
             }
             dp[p.charAt(i) - 'a'] = Math.max(dp[p.charAt(i) - 'a'], count);
         }
         return Arrays.stream(dp).sum();
     }
 }
 ​

\