HackerRank Super Functional Strings Solution Yashwant Parihar, May 1, 2023May 1, 2023 In this post, we will solve HackerRank Super Functional Strings Problem Solution. We define a function, F. on a string, P, as follows:= (length(Pydistinct;P) ) % (10ยบ + 7) F(P)=where:length(P) denotes the number of characters in string P. distinct (P) denotes the number of distinct characters in string P.Consuela loves creating string challenges and she needs your help testing her newest one! Given a string, S, consisting of N lowercase letters, compute the summation of function F (provided above) over all possible distinct substrings of S. As the result is quite large, print it modulo 109 + 7.Input FormatThe first line contains a single integer, T, denoting the number of test cases.Each of the T subsequent lines contains a string, S. Sample Input 3 aa aba abc Sample Output 3 19 38 ExplanationTest 0:“a” and “aa” are the only distinct substrings.F(“a”) (11) % 1000000007 = 1 F(“aa”) (21) % 1000000007 = 2 ans = (1+2) % 1000000007 = 3Test 1:“a”, “b”, “ab”, “aba”, and “ba” are the only distinct substrings.F(“a”) (11) % 1000000007 = 1F(“ab”) (22) % 1000000007 = 4 F(“aba”) (32) % 1000000007 = 9 F(“b”) (11) % 1000000007 = 1F(“ba”) (22) % 1000000007 = 4 HackerRank Super Functional Strings Problem Solution Super Functional Strings C Solution #include <stdio.h> #include <stdlib.h> #include <string.h> #define A_SIZE 26 #define MIN_C 'a' #define MOD 1000000007 typedef struct _st_node st_node; typedef struct _st_edge st_edge; struct _st_node{ st_node *suffix_link; st_edge *edges[A_SIZE+1]; }; struct _st_edge{ int from; int to; int suffix_index; st_node *node; }; void print(st_node *root,int len); void suffix_tree(st_node *root,char *str,int len); long long modPow(long long a,int x); void sort_a(int*a,int size); void merge(int*a,int*left,int*right,int left_size, int right_size); char str[100001]; int dp[100000][26]; long long ans,pows[26][100001]; int main(){ int T,len,i,j; st_node root; for(i=0;i<26;i++) for(j=1;j<=100000;j++) pows[i][j]=(pows[i][j-1]+modPow(j,i+1))%MOD; scanf("%d",&T); while(T--){ scanf("%s",str); len=strlen(str); for(i=0;i<26;i++) dp[len-1][i]=-1; dp[len-1][str[len-1]-MIN_C]=len-1; for(i=len-2;i>=0;i--){ memcpy(&dp[i][0],&dp[i+1][0],26*sizeof(int)); dp[i][str[i]-MIN_C]=i; } suffix_tree(&root,str,len); ans=0; print(&root,0); printf("%lld\n",ans); } return 0; } void print(st_node *root,int len){ int i,j,idx,from,to,s,dc,last,t,a[26]; if(!root) return; for(i=0;i<A_SIZE;i++) if(root->edges[i]){ idx=root->edges[i]->suffix_index; from=idx+len; to=idx+len+root->edges[i]->to-root->edges[i]->from; s=dc=0; last=idx+len-1; for(j=0;j<26;j++) if(dp[idx][j]!=-1 && dp[idx][j]<from) dc++; else if(dp[idx][j]>=from && dp[idx][j]<=to) a[s++]=dp[idx][j]; sort_a(a,s); for(j=0;j<s;j++,dc++){ t=a[j]-1; if(dc) ans=(ans+pows[dc-1][t-idx+1]-pows[dc-1][last-idx+1]+MOD)%MOD; last=t; } t=to; ans=(ans+pows[dc-1][t-idx+1]-pows[dc-1][last-idx+1]+MOD)%MOD; print(root->edges[i]->node,len+root->edges[i]->to-root->edges[i]->from+1); } return; } void suffix_tree(st_node *root,char *str,int len){ int a_edge,a_len=0,remainder=0,need_insert,from,i; st_node *a_node=root,*pre_node,*t_node; st_edge *t_edge; memset(root,0,sizeof(st_node)); for(i=0;i<=len;i++){ need_insert=0; pre_node=NULL; remainder++; if(i==len) need_insert=1; else if(a_len) if(str[a_node->edges[a_edge]->from+a_len]==str[i]) if(a_node->edges[a_edge]->from+a_len==a_node->edges[a_edge]->to){ a_node=a_node->edges[a_edge]->node; a_len=0; } else a_len++; else need_insert=1; else if(a_node->edges[str[i]-MIN_C]) if(a_node->edges[str[i]-MIN_C]->from==a_node->edges[str[i]-MIN_C]->to) a_node=a_node->edges[str[i]-MIN_C]->node; else{ a_edge=str[i]-MIN_C; a_len=1; } else need_insert=1; if(need_insert) for(;remainder>0;remainder--){ if(!a_len) if(i==len){ a_node->edges[A_SIZE]=(st_edge*)malloc(sizeof(st_edge)); a_node->edges[A_SIZE]->suffix_index=i-remainder+1; a_node->edges[A_SIZE]->node=NULL; } else{ if(a_node->edges[str[i]-MIN_C]){ if(pre_node) pre_node->suffix_link=a_node; if(a_node->edges[str[i]-MIN_C]->from==a_node->edges[str[i]-MIN_C]->to) a_node=a_node->edges[str[i]-MIN_C]->node; else{ a_edge=str[i]-MIN_C; a_len=1; } break; } t_edge=(st_edge*)malloc(sizeof(st_edge)); t_edge->from=i; t_edge->to=len-1; t_edge->suffix_index=i-remainder+1; t_edge->node=NULL; a_node->edges[str[i]-MIN_C]=t_edge; t_node=a_node; } else{ if(i!=len && str[a_node->edges[a_edge]->from+a_len]==str[i]){ if(pre_node) pre_node->suffix_link=a_node; if(a_node->edges[a_edge]->from+a_len==a_node->edges[a_edge]->to){ a_node=a_node->edges[a_edge]->node; a_len=0; } else a_len++; break; } t_node=(st_node*)malloc(sizeof(st_node)); memset(t_node,0,sizeof(st_node)); t_edge=(st_edge*)malloc(sizeof(st_edge)); t_edge->from=a_node->edges[a_edge]->from+a_len; t_edge->to=a_node->edges[a_edge]->to; t_edge->suffix_index=a_node->edges[a_edge]->suffix_index; t_edge->node=a_node->edges[a_edge]->node; from=a_node->edges[a_edge]->from; a_node->edges[a_edge]->node=t_node; a_node->edges[a_edge]->to=a_node->edges[a_edge]->from+a_len-1; t_node->edges[str[t_edge->from]-MIN_C]=t_edge; if(i==len){ t_node->edges[A_SIZE]=(st_edge*)malloc(sizeof(st_edge)); t_node->edges[A_SIZE]->suffix_index=i-remainder+1; t_node->edges[A_SIZE]->node=NULL; } else{ t_edge=(st_edge*)malloc(sizeof(st_edge)); t_edge->from=i; t_edge->to=len-1; t_edge->suffix_index=i-remainder+1; t_edge->node=NULL; t_node->edges[str[i]-MIN_C]=t_edge; } } if(pre_node) pre_node->suffix_link=t_node; pre_node=t_node; if(a_node==root && a_len>0){ if(remainder>1) a_edge=str[i-remainder+2]-MIN_C; from=i-remainder+2; a_len--; } else if(a_node!=root) if(a_node->suffix_link) a_node=a_node->suffix_link; else a_node=root; while(a_len>0 && a_len>=a_node->edges[a_edge]->to-a_node->edges[a_edge]->from+1){ a_len-=a_node->edges[a_edge]->to-a_node->edges[a_edge]->from+1; from+=a_node->edges[a_edge]->to-a_node->edges[a_edge]->from+1; a_node=a_node->edges[a_edge]->node; a_edge=str[from]-MIN_C; } } } return; } long long modPow(long long a,int x){ long long res = 1; while(x>0){ if(x%2) res=(res*a)%MOD; a=(a*a)%MOD; x>>=1; } return res; } void sort_a(int*a,int size){ if (size < 2) return; int m = (size+1)/2,i; int *left,*right; left=(int*)malloc(m*sizeof(int)); right=(int*)malloc((size-m)*sizeof(int)); for(i=0;i<m;i++) left[i]=a[i]; for(i=0;i<size-m;i++) right[i]=a[i+m]; sort_a(left,m); sort_a(right,size-m); merge(a,left,right,m,size-m); free(left); free(right); return; } void merge(int*a,int*left,int*right,int left_size, int right_size){ int i = 0, j = 0; while (i < left_size|| j < right_size) { if (i == left_size) { a[i+j] = right[j]; j++; } else if (j == right_size) { a[i+j] = left[i]; i++; } else if (left[i] <= right[j]) { a[i+j] = left[i]; i++; } else { a[i+j] = right[j]; j++; } } return; } Super Functional Strings C++ Solution #include <bits/stdc++.h> using namespace std; typedef long long ll; ll mod = 1e9+7; const int nax = 1e5+10; ll sum_pow[27][nax]; int main() { for (int i = 0; i <= 26; i++) { for (int j = 1; j < nax; j++) { ll v = 1; if (i) { v = (sum_pow[i-1][j]-sum_pow[i-1][j-1])*j; } sum_pow[i][j] = (sum_pow[i][j-1]+v) % mod; } } ios::sync_with_stdio(0); cin.tie(0); int t; cin >> t; while (t--) { string s; cin >> s; int n = s.size(); assert(n); vector<int> sa(n), rank(n), tmp(n); for (int i = 0; i < n; i++) sa[i] = i, rank[i] = s[i]; for (int d = 1;; d *= 2) { auto cmp = [&](int i, int j) { auto a = make_pair(rank[i], i+d < n ? rank[i+d] : -1); auto b = make_pair(rank[j], j+d < n ? rank[j+d] : -1); return a < b; }; sort(sa.begin(), sa.end(), cmp); int c = 0; for (int i = 0;; i++) { tmp[sa[i]] = c; if (i == n-1) break; c += cmp(sa[i],sa[i+1]); } swap(tmp,rank); if (c == n-1) break; } s += '@'; vector<int> lcp(n,0); int k = 0; for (int i = 0; i < n; i++) { int j = rank[i]; if (j == n-1) continue; while (s[sa[j]+k] == s[sa[j+1]+k]) k++; lcp[j+1] = k; if (k) k--; } /*for (int i = 0; i < n; i++) { cout << s.substr(sa[i]) << ' ' << lcp[i] << endl; } cout << endl;*/ vector<vector<int>> next(n+1, vector<int>(26,n)); for (int i = n-1; i >= 0; i--) { next[i] = next[i+1]; next[i][s[i]-'a'] = i; } vector<vector<int>> count(n+1, vector<int>(26,0)); for (int i = 0; i < n; i++) { for (int j = 0; j < 26; j++) { count[i+1][j] = count[i][j]+(s[i] == 'a'+j); } } ll ans = 0; for (int i = 0; i < n; i++) { int l = lcp[i]; int mask = 0; for (int j = 0; j < 26; j++) if (count[sa[i]+l][j]-count[sa[i]][j]) mask |= 1<<j; int p = sa[i]+l; //cout << s.substr(sa[i]) << endl; //cout << s.substr(sa[i], l) << ": "; while (p < n) { int q = n; for (int j = 0; j < 26; j++) { if (!(mask>>j&1)) q = min(q, next[p][j]); } //cout << s.substr(p,q-p) << '|'; auto sum = sum_pow[__builtin_popcount(mask)]; (ans += sum[q-sa[i]]-sum[p-sa[i]]) %= mod; if (q == n) break; int old_mask = mask; for (int j = 0; j < 26; j++) if (count[q+1][j]-count[sa[i]][j]) mask |= 1<<j; assert(mask != old_mask); p = q; } //cout << endl; //for (int j = l+1; sa[i]+j <= s.size(); j++) //cout << s.substr(sa[i],j) << ' '; //cout << endl; } cout << (ans%mod+mod)%mod << endl; } } Super Functional Strings C Sharp Solution using System.CodeDom.Compiler; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Text.RegularExpressions; using System.Text; using System; class Result { /* * Complete the 'superFunctionalStrings' function below. * * The function is expected to return an INTEGER. * The function accepts STRING s as parameter. */ private static long[][] ar; public static void inIt() { ar = new long[100001][]; long mod = 1000000007; ar[0] = new long[27]; for (int i = 1; i < 100001; i++) { ar[i] = new long[27]; ar[i][1] = i; for (int j = 2; j < 27; j++) { ar[i][j] = ar[i][j - 1] * i % mod; } } for (int i = 1; i < 27; i++) { ar[0][i] = 0; long t = ar[1][i]; for (int j = 2; j < 100001; j++) { ar[j][i] = (t + ar[j][i]) % mod; t = ar[j][i]; } } } public static int superFunctionalStrings(string s) { int n = s.Length, a1,a2, lg=0; Dictionary<int, int>[] dc = new Dictionary<int, int>[n]; dc[n - 1] = new Dictionary<int, int>(); dc[n - 1].Add(s[n - 1] - 'a', n - 1); for (int i = n-2; i >= 0; i--) { dc[i] = new Dictionary<int, int>(dc[i + 1]); if (dc[i].ContainsKey(s[i] - 'a')) dc[i][s[i] - 'a'] = i; else dc[i].Add(s[i] - 'a', i); } Dictionary<ValueTuple<int, int, int>, int> d = new Dictionary<ValueTuple<int, int, int>, int>(); long res = 0, mod = 1000000007; List<int> list = dc[0].Values.ToList(); list.Sort(); list.Add(n); res = countIt(list,lg); bool goOn = true; for (int i = 1; i < n; i++) { goOn = true; a1 = 0; a2 = i; lg = 0; while (goOn) { goOn = false; while (a2 < n && s[a1]==s[a2]) { a1++; a2++; lg++; } if (a2<n) { if (d.ContainsKey((a1,lg,s[a2]))) { a1 = d[(a1, lg, s[a2])]; goOn = true; } else d.Add((a1, lg, s[a2]), a2); } } if (a2 < n) { list = dc[i].Values.ToList(); list.Sort(); list.Add(n); res = (res + countIt(list, lg)) % mod; } } return (int)res; } private static int countIt(List<int> list, int lg) { long res = 0, mod = 1000000007; int n = list.Count, str= list[0], m; for (int i = 1; i < n; i++) { m = list[i] - str; if (m - lg <1) continue; res = (res + ar[m][i] - ar[lg][i])%mod; if (res < 0) res += mod; lg = m; } return (int)res; } } class Solution { public static void Main(string[] args) { TextWriter textWriter = new StreamWriter(@System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true); int t = Convert.ToInt32(Console.ReadLine().Trim()); Result.inIt(); for (int tItr = 0; tItr < t; tItr++) { string s = Console.ReadLine(); int result = Result.superFunctionalStrings(s); textWriter.WriteLine(result); } textWriter.Flush(); textWriter.Close(); } } Super Functional Strings Java Solution import java.io.*; import java.util.*; public class Solution { static final int MOD = 1_000_000_007; static final int MAX = 100000; static class Suffix { int index; int[] rank = new int[2]; } static Comparator<Suffix> cmp = (a, b) -> { return (a.rank[0] == b.rank[0]) ? a.rank[1] - b.rank[1] : a.rank[0] - b.rank[0]; }; static int[] invSuff = new int[MAX]; static int[] suffixArr = new int[MAX]; static int[] lcp = new int[MAX]; static void buildSuffixArray(char[] txt) { int n = txt.length; Suffix[] suffixes = new Suffix[n]; for (int i = 0; i < n; i++) { suffixes[i] = new Suffix(); suffixes[i].index = i; suffixes[i].rank[0] = txt[i] - 'a'; suffixes[i].rank[1] = ((i + 1) < n) ? (txt[i + 1] - 'a') : -1; } Arrays.sort(suffixes, cmp); int[] ind = new int[n]; for (int k = 4; k < 2 * n; k = k * 2) { int rank = 0; int prev_rank = suffixes[0].rank[0]; suffixes[0].rank[0] = rank; ind[suffixes[0].index] = 0; for (int i = 1; i < n; i++) { if (suffixes[i].rank[0] == prev_rank && suffixes[i].rank[1] == suffixes[i - 1].rank[1]) { prev_rank = suffixes[i].rank[0]; suffixes[i].rank[0] = rank; } else { prev_rank = suffixes[i].rank[0]; suffixes[i].rank[0] = ++rank; } ind[suffixes[i].index] = i; } for (int i = 0; i < n; i++) { int nextindex = suffixes[i].index + k / 2; suffixes[i].rank[1] = (nextindex < n) ? suffixes[ind[nextindex]].rank[0] : -1; } Arrays.sort(suffixes, cmp); } for (int i = 0; i < n; i++) { suffixArr[i] = suffixes[i].index; invSuff[suffixArr[i]] = i; } } static void kasai(char[] txt) { int n = txt.length; int k = 0; for (int i = 0; i < n; i++) { if (invSuff[i] == n - 1) { k = 0; continue; } int j = suffixArr[invSuff[i] + 1]; while (i + k < n && j + k < n && txt[i + k] == txt[j + k]) { k++; } lcp[invSuff[i]] = k; if (k > 0) { k--; } } } static long superFunctionalStrings(char[] s, int[][] map) { buildSuffixArray(s); kasai(s); int len = s.length; @SuppressWarnings("unchecked") Map<Integer, Integer>[] letterPlaceArr = new Map[len]; letterPlaceArr[len - 1] = new HashMap<>(); letterPlaceArr[len - 1].put((s[len - 1]) - 'a', len - 1); for (int i = len - 2; i >= 0; i--) { letterPlaceArr[i] = new HashMap<>(letterPlaceArr[i + 1]); letterPlaceArr[i].put(s[i] - 'a', i); } long result = 0; for (int i = 0; i < len; i++) { int nowLen = i == 0 ? 0 : lcp[i - 1]; int startIndex = suffixArr[i]; List<Integer> tempArr = new ArrayList<Integer>(letterPlaceArr[startIndex].values()); tempArr.add(len); Collections.sort(tempArr); for (int j = 1, tempLen = tempArr.size(); j < tempLen; j++) { if (tempArr.get(j) - startIndex <= nowLen) { continue; } int diff = map[tempArr.get(j) - startIndex][j] - map[Math.max(tempArr.get(j-1) - startIndex, nowLen)][j]; if (diff < 0) { diff += MOD; } result = (result + diff) % MOD; } } return result; } static int[][] init() { int[][] map = new int[100001][28]; for (int i = 1; i <= 100000; i++) { long temp = 1; for (int j = 1; j <= 26; j++) { temp = (temp * i) % MOD; map[i][j] = (int)temp; } } for (int j = 1; j <= 26; j++) { map[0][j] = 0; int temp = map[1][j]; for (int i = 2; i <= 100000; i++) { map[i][j] = (temp + map[i][j]) % MOD; temp = map[i][j]; } } return map; } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH"))); StringTokenizer st = new StringTokenizer(br.readLine()); int t = Integer.parseInt(st.nextToken()); int[][] map = init(); for (int i = 0; i < t; i++) { char[] s = br.readLine().toCharArray(); long result = superFunctionalStrings(s, map); bw.write(String.valueOf(result)); bw.newLine(); } bw.close(); br.close(); } } Super Functional Strings JavaScript Solution 'use strict'; const fs = require('fs'); process.stdin.resume(); process.stdin.setEncoding('utf-8'); let inputString = ''; let currentLine = 0; process.stdin.on('data', inputStdin => { inputString += inputStdin; }); process.stdin.on('end', _ => { inputString = inputString.trim().split('\n').map(str => str.trim()); main(); }); function readLine() { return inputString[currentLine++]; } /* * Complete the superFunctionalStrings function below. */ function superFunctionalStrings(s) { var i, j; var str_list = []; var s_str = ""; for (i = 0; i < s.length; i++) { for (j = i + 1; j < s.length + 1; j++) { s_str = s.substring(i, j); if (str_list.indexOf(s_str) == -1) { str_list.push(s_str); } } } var chr_list; var sum = 0; console.log("---------------------------------"); for (i = 0; i < str_list.length; i++) { chr_list = []; if (str_list[i] == "") { continue; } for (j = 0; j < str_list[i].length; j++) { if (str_list[i][j] == '') { continue; } if (chr_list.indexOf(str_list[i][j]) == -1) { chr_list.push(str_list[i][j]); } } console.log(str_list[i] + " " + (findPow(str_list[i].length, chr_list.length))); console.log(str_list[i].length + " " + chr_list.length); sum = (sum + (findPow(str_list[i].length, chr_list.length))) % (Math.pow(10, 9) + 7) } return sum; } function findPow(a, b) { var i; var result = 1; for (i = 0; i < b; i++) { result = (result * a) % (Math.pow(10, 9) + 7) } return result; } function main() { const ws = fs.createWriteStream(process.env.OUTPUT_PATH); const t = parseInt(readLine(), 10); for (let tItr = 0; tItr < t; tItr++) { const s = readLine(); let result = superFunctionalStrings(s); ws.write(result + "\n"); } ws.end(); } Super Functional Strings Python Solution from string import ascii_lowercase from bisect import bisect_left, bisect_right from itertools import zip_longest, islice MOD = 7 + 10 ** 9 N = 10 ** 5 sum_pow = [[0] * (N + 1) for k in range(27)] for k in range(1, 27): for n in range(1, N + 1): sum_pow[k][n] = (sum_pow[k][n - 1] + pow(n, k, MOD)) % MOD def get_sp(left, right, k): if left > right or right <= 0: return 0 if left <= 0: return sum_pow[k][right] return (sum_pow[k][right] + MOD - sum_pow[k][left - 1]) % MOD def all_occ(s): n = len(s) occ = [[] for _ in range(26)] for i in range(n): occ[ord(s[i]) - ord('a')].append(i) return occ def occ_from_i(occ, i): occ_i = [] for j in range(26): if len(occ[j]) == 0 or i > occ[j][-1]: continue first = bisect_left(occ[j], i) occ_i.append(occ[j][first]) return sorted(occ_i) def sorted_idx(items): unique = sorted(set(items)) idx = dict(zip(unique, range(len(unique)))) return [idx[v] for v in items] def suffix_array(s): n = len(s) k = 1 sa = sorted_idx(s) while max(sa) < n - 1: sa = sorted_idx([a * (n + 1) + b + 1 for (a, b) in zip_longest(sa, islice(sa, k, None), fillvalue=-1)]) k <<= 1 return sa def lcp_sa(s): inv_sa = suffix_array(s) n = len(inv_sa) sa = [0] * n for i in range(n): sa[inv_sa[i]] = i lcp = [0] * n k = 0 for i in range(n): if inv_sa[i] == n - 1: k = 0 continue j = sa[inv_sa[i]+1] while i + k < n and j + k < n and s[i + k] == s[j + k]: k += 1 lcp[inv_sa[i] + 1] = k if k > 0: k -= 1 return sa, lcp def solve(s): n = len(s) occ = all_occ(s) sa, lcp = lcp_sa(s) ans = 0 #print(sa) #print(lcp) for i in range(n): o = occ_from_i(occ, sa[i]) t = sa[i] + lcp[i] if t >= o[-1]: ans = (ans + get_sp(lcp[i] + 1, n - sa[i], len(o))) % MOD continue k = bisect_right(o, t) ans = (ans + get_sp(lcp[i] + 1, o[k] - sa[i], k)) % MOD for j in range(k + 1, len(o)): ans = (ans + get_sp(o[j - 1] - sa[i] + 1, o[j] - sa[i], j)) % MOD ans = (ans + get_sp(o[-1] - sa[i] + 1, n - sa[i], len(o))) % MOD return ans def sum_p_bf(left, right, k): ans = 0 for n in range(max(left, 1), right + 1): ans = (ans + pow(n, k, MOD)) % MOD return ans q = int(input().strip()) for _ in range(q): string = input().strip() print(solve(string)) c C# C++ HackerRank Solutions java javascript python CcppCSharpHackerrank Solutionsjavajavascriptpython