We define the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s will look like this:


	"...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....".


Given a string p, return the number of unique non-empty substrings of p are present in s.

&nbsp;
Example 1:

Input: p = "a"
Output: 1
Explanation: Only the substring "a" of p is in s.


Example 2:

Input: p = "cac"
Output: 2
Explanation: There are two substrings ("a", "c") of p in s.


Example 3:

Input: p = "zab"
Output: 6
Explanation: There are six substrings ("z", "a", "b", "za", "ab", and "zab") of p in s.


&nbsp;
Constraints:


	1 &lt;= p.length &lt;= 105
	p consists of lowercase English letters.


def get_next(char):
    x = ord(char)-ord('a')
    x = (x+1)%26
    return chr(ord('a') + x)
class Solution:
    def findSubstringInWraproundString(self, p: str) -> int:
        i = 0
        n = len(p)
        map_ = collections.defaultdict(int)
        while i<n:
            start = i
            prev_val = p[i]
            while i+1<n and get_next(prev_val) == p[i+1]:
                prev_val = p[i+1]
                i+=1
            while start <= i:
                curr_val = i-start+1
                map_[p[start]] = max(map_[p[start]], curr_val)
                start += 1
            i+=1
        return sum(map_.values())
// One Pass Counting Solution
// 1. check cur-prev == 1 or -25 to track the length of longest continuos subtring.
// 2. counts to track the longest continuos subtring starting with current character.
// Time complexity: O(N)
// Space complexity: O(1)
class Solution {
    public int findSubstringInWraproundString(String p) {
        final int N = p.length();
        int res = 0, len = 1;
        int[] counts = new int[26];
        for (int i = 0; i < N; i++) {
            char ch = p.charAt(i);
            if (i > 0 && (ch - p.charAt(i-1) == 1 || ch - p.charAt(i-1) == -25)) {
                len++;
            } else {
                len = 1;
            }
            int idx = ch - 'a';
            counts[idx] = Math.max(counts[idx], len);
        }
        for (int count : counts) {
            res += count;
        }
        return res;
    }
}
class Solution {
public:

    int findSubstringInWraproundString(string p) {
        unordered_map<char, int> mp;

        // if the characters are not contiguous and also check whether after 'z' I am getting 'a'. If so, reset the streak to 1
        // else streak++

        int streak = 0;

        for (int i = 0; i < p.size(); i++) {

            // contiguous
            if (i and (p[i] - p[i - 1] == 1)) streak++;

            // z...a case
            else if (i and (p[i] == 'a' and p[i - 1] == 'z')) streak++;

            else streak = 1;

            mp[p[i]] = max(mp[p[i]], streak);
        }

        // why sum? cuz there might be multiple substrings when the streak's broken for one

        int ans = 0;
        for (auto x : mp) {
            ans += x.second;
        }

        return ans;
    }
};
var findSubstringInWraproundString = function(p) {
	const dp = Array(26).fill(0);
	const origin = 'a'.charCodeAt(0);
	let count = 0;

	for (let index = 0; index < p.length; index++) {
		const code = p.charCodeAt(index);
		const preCode = p.charCodeAt(index - 1);
		const pos = code - origin;

		count = code - preCode === 1 || preCode - code === 25
			? count + 1
			: 1;

		dp[pos] = Math.max(count, dp[pos]);
	}

	return dp.reduce((total, count) => total + count);
};
Unique Substrings in Wraparound String