Dada una string binaria S que consta de solo 0 y 1. Cuente el número de substrings de esta string de modo que la longitud de la substring sea divisible por el número de 1 en la substring.
Ejemplos:
Entrada: S = “01010”
Salida: 10Entrada: S = “1111100000”
Salida: 25
Enfoque ingenuo:
- Repita todas las substrings y para cada substring cuente el número de 1. Si la longitud de la substring es divisible por el conteo de 1, aumente el conteo. Este enfoque tomará tiempo O(N 3 ).
- Para hacer que la solución sea más eficiente, en lugar de recorrer toda la substring para contar el número de 1 que contiene, podemos usar Prefix Sum Array .
número de 1 en la substring [l: r] = prefix_sum[r] – prefix_sum[l – 1]
A continuación se muestra la implementación del enfoque anterior.
C++
// C++ program to count number of // substring under given condition #include <bits/stdc++.h> using namespace std; // Function return count of // such substring int countOfSubstrings(string s) { int n = s.length(); int prefix_sum[n] = { 0 }; // Mark 1 at those indices // where '1' appears for (int i = 0; i < n; i++) { if (s[i] == '1') prefix_sum[i] = 1; } // Take prefix sum for (int i = 1; i < n; i++) prefix_sum[i] += prefix_sum[i - 1]; int answer = 0; // Iterate through all the // substrings for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int countOfOnes = prefix_sum[j] - (i - 1 >= 0 ? prefix_sum[i - 1] : 0); int length = j - i + 1; if (countOfOnes > 0 && length % countOfOnes == 0) answer++; } } return answer; } // Driver Code int main() { string S = "1111100000"; cout << countOfSubstrings(S); return 0; }
Java
// Java program to count number of // subString under given condition import java.util.*; class GFG{ // Function return count of // such substring static int countOfSubStrings(String s) { int n = s.length(); int []prefix_sum = new int[n]; // Mark 1 at those indices // where '1' appears for (int i = 0; i < n; i++) { if (s.charAt(i) == '1') prefix_sum[i] = 1; } // Take prefix sum for (int i = 1; i < n; i++) prefix_sum[i] += prefix_sum[i - 1]; int answer = 0; // Iterate through all the // subStrings for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int countOfOnes = prefix_sum[j] - (i - 1 >= 0 ? prefix_sum[i - 1] : 0); int length = j - i + 1; if (countOfOnes > 0 && length % countOfOnes == 0) answer++; } } return answer; } // Driver Code public static void main(String[] args) { String S = "1111100000"; System.out.print(countOfSubStrings(S)); } } // This code contributed by sapnasingh4991
Python3
# Python3 program to count number of # substring under given condition # Function return count of # such substring def countOfSubstrings(s): n = len(s) prefix_sum = [0 for i in range(n)] # Mark 1 at those indices # where '1' appears for i in range(n): if (s[i] == '1'): prefix_sum[i] = 1 # Take prefix sum for i in range(1, n, 1): prefix_sum[i] += prefix_sum[i - 1] answer = 0 # Iterate through all the # substrings for i in range(n): for j in range(i, n, 1): if (i - 1 >= 0): countOfOnes = prefix_sum[j]- prefix_sum[i - 1] else: countOfOnes = prefix_sum[j] length = j - i + 1 if (countOfOnes > 0 and length % countOfOnes == 0): answer += 1 return answer # Driver Code if __name__ == '__main__': S = "1111100000" print(countOfSubstrings(S)) # This code is contributed by Bhupendra_Singh
C#
// C# program to count number of // subString under given condition using System; class GFG{ // Function return count of // such substring static int countOfSubStrings(String s) { int n = s.Length; int []prefix_sum = new int[n]; // Mark 1 at those indices // where '1' appears for(int i = 0; i < n; i++) { if (s[i] == '1') prefix_sum[i] = 1; } // Take prefix sum for(int i = 1; i < n; i++) prefix_sum[i] += prefix_sum[i - 1]; int answer = 0; // Iterate through all the // subStrings for(int i = 0; i < n; i++) { for(int j = i; j < n; j++) { int countOfOnes = prefix_sum[j] - (i - 1 >= 0 ? prefix_sum[i - 1] : 0); int length = j - i + 1; if (countOfOnes > 0 && length % countOfOnes == 0) answer++; } } return answer; } // Driver Code public static void Main(String[] args) { String S = "1111100000"; Console.Write(countOfSubStrings(S)); } } // This code is contributed by Rohit_ranjan
Javascript
<script> // Javascript program to count number of // subString under given condition // Function return count of // such substring function countOfSubStrings(s) { let n = s.length; let prefix_sum = Array.from({length: n}, (_, i) => 0); // Mark 1 at those indices // where '1' appears for (let i = 0; i < n; i++) { if (s[i] == '1') prefix_sum[i] = 1; } // Take prefix sum for (let i = 1; i < n; i++) prefix_sum[i] += prefix_sum[i - 1]; let answer = 0; // Iterate through all the // subStrings for (let i = 0; i < n; i++) { for (let j = i; j < n; j++) { let countOfOnes = prefix_sum[j] - (i - 1 >= 0 ? prefix_sum[i - 1] : 0); let length = j - i + 1; if (countOfOnes > 0 && length % countOfOnes == 0) answer++; } } return answer; } // Driver Code let S = "1111100000"; document.write(countOfSubStrings(S)); </script>
25
Complejidad del tiempo: O(N 2 )
Espacio Auxiliar: O(N)
Enfoque eficiente:
- Usemos la array de suma de prefijos como se discutió en el enfoque anterior. Tomemos una substring [l:r] que sigue la condición dada, podemos decir que:
r – l + 1 = k * (prefix_sum[r] – prefix_sum[l-1]), donde k es un número entero
- Esto también se puede escribir como:
r – k * suma_prefijo[r] = l – 1 – k * suma_prefijo[l-1]
Observando esta ecuación, podemos crear otra array de B[i] = i – k * prefix_sum[i], para 0 <= k < n. Entonces, el problema ahora es calcular el número de pares de enteros iguales en B para cada k.
- Tomemos un número fijo x. Si k > x, entonces como r – l + 1 <= n (para cualquier par de l, r), obtenemos la siguiente desigualdad:
suma_prefijo[r] – suma_prefijo[l-1] = (r – l + 1)/k <= n/x
- Esto continúa para mostrar que el número de unos y k no es grande en las substrings que satisfacen las condiciones dadas. (esto es solo para la estimación de la eficiencia). Ahora, para k <= x, necesitamos calcular el número de pares de enteros iguales. Aquí se cumple la siguiente desigualdad:
(-1) *n*x <= i – k – suma_prefijo[i] <= n
- Entonces, podemos poner todos los números en una array para cada k de forma independiente y encontrar el número de enteros iguales.
- El siguiente paso sería fijar los valores de l e iterar sobre el número de 1 en la string, y para cada valor obtener los límites de r. Para una cuenta dada del número de 1, podemos evaluar qué resto dará r. El problema ahora es calcular el número de números enteros en algunos segmentos, lo que da un resto fijo (rem) cuando se divide por algún número entero fijo. Este cálculo se puede hacer en O(1). Además, tenga en cuenta que es importante contar solo los valores de r para los que k > x.
A continuación se muestra la implementación del enfoque anterior.
C++
// C++ program to count number of // substring under given condition #include <bits/stdc++.h> using namespace std; // Function return count of such // substring int countOfSubstrings(string s) { int n = s.length(); // Selection of adequate x value int x = sqrt(n); // Store where 1's are located vector<int> ones; for (int i = 0; i < n; i++) { if (s[i] == '1') ones.push_back(i); } // If there are no ones, // then answer is 0 if (ones.size() == 0) return 0; // For ease of implementation ones.push_back(n); // Count storage vector<int> totCount(n * x + n); int sum = 0; // Iterate on all k values less // than fixed x for (int k = 0; k <= x; k++) { // Keeps a count of 1's occured // during string traversal int now = 0; totCount[k * n]++; // Iterate on string and modify // the totCount for (int j = 1; j <= n; j++) { // If this character is 1 if (s[j - 1] == '1') now++; int index = j - k * now; // Add to the final sum/count sum += totCount[index + k * n]; // Increase totCount at exterior // position totCount[index + k * n]++; } now = 0; totCount[k * n]--; for (int j = 1; j <= n; j++) { if (s[j - 1] == '1') now++; int index = j - k * now; // Reduce totCount at index + k*n totCount[index + k * n]--; } } // Slightly modified prefix sum storage int prefix_sum[n]; memset(prefix_sum, -1, sizeof(prefix_sum)); // Number of 1's till i-1 int cnt = 0; for (int i = 0; i < n; i++) { prefix_sum[i] = cnt; if (s[i] == '1') cnt++; } // Traversing over string considering // each position and finding bounds // and count using the inequalities for (int k = 0; k < n; k++) { for (int j = 1; j <= (n / x) && prefix_sum[k] + j <= cnt; j++) { // Calculating bounds for l and r int l = ones[prefix_sum[k] + j - 1] - k + 1; int r = ones[prefix_sum[k] + j] - k; l = max(l, j * (x + 1)); // If valid then add to answer if (l <= r) { sum += r / j - (l - 1) / j; } } } return sum; } int main() { string S = "1111100000"; cout << countOfSubstrings(S); return 0; }
Java
// Java program to count number of // subString under given condition import java.util.*; class GFG{ // Function return count of such // substring static int countOfSubStrings(String s) { int n = s.length(); // Selection of adequate x value int x = (int)Math.sqrt(n); // Store where 1's are located Vector<Integer> ones = new Vector<Integer>(); for(int i = 0; i < n; i++) { if (s.charAt(i) == '1') ones.add(i); } // If there are no ones, // then answer is 0 if (ones.size() == 0) return 0; // For ease of implementation ones.add(n); // Count storage int []totCount = new int[n * x + n]; int sum = 0; // Iterate on all k values less // than fixed x for(int k = 0; k <= x; k++) { // Keeps a count of 1's occured // during String traversal int now = 0; totCount[k * n]++; // Iterate on String and modify // the totCount for(int j = 1; j <= n; j++) { // If this character is 1 if (s.charAt(j - 1) == '1') now++; int index = j - k * now; // Add to the final sum/count sum += totCount[index + k * n]; // Increase totCount at exterior // position totCount[index + k * n]++; } now = 0; totCount[k * n]--; for(int j = 1; j <= n; j++) { if (s.charAt(j - 1) == '1') now++; int index = j - k * now; // Reduce totCount at index + k*n totCount[index + k * n]--; } } // Slightly modified prefix sum storage int []prefix_sum = new int[n]; Arrays.fill(prefix_sum, -1); // Number of 1's till i-1 int cnt = 0; for(int i = 0; i < n; i++) { prefix_sum[i] = cnt; if (s.charAt(i) == '1') cnt++; } // Traversing over String considering // each position and finding bounds // and count using the inequalities for(int k = 0; k < n; k++) { for(int j = 1; j <= (n / x) && prefix_sum[k] + j <= cnt; j++) { // Calculating bounds for l and r int l = ones.get(prefix_sum[k] + j - 1)- k + 1; int r = ones.get(prefix_sum[k] + j) - k; l = Math.max(l, j * (x + 1)); // If valid then add to answer if (l <= r) { sum += r / j - (l - 1) / j; } } } return sum; } // Driver code public static void main(String[] args) { String S = "1111100000"; System.out.print(countOfSubStrings(S)); } } // This code is contributed by Amit Katiyar
Python3
# Python3 program to count number of # substring under given condition import math # Function return count of such # substring def countOfSubstrings(s): n = len(s) # Selection of adequate x value x = int(math.sqrt(n)) # Store where 1's are located ones = [] for i in range (n): if (s[i] == '1'): ones.append(i) # If there are no ones, # then answer is 0 if (len(ones) == 0): return 0 # For ease of implementation ones.append(n) # Count storage totCount = [0] * (n * x + n) sum = 0 # Iterate on all k values less # than fixed x for k in range(x + 1): # Keeps a count of 1's occured # during string traversal now = 0 totCount[k * n] += 1 # Iterate on string and modify # the totCount for j in range(1, n + 1): # If this character is 1 if (s[j - 1] == '1'): now += 1 index = j - k * now # Add to the final sum/count sum += totCount[index + k * n] # Increase totCount at exterior # position totCount[index + k * n] += 1 now = 0 totCount[k * n] -= 1 for j in range(1, n + 1): if (s[j - 1] == '1'): now += 1 index = j - k * now # Reduce totCount at index + k*n totCount[index + k * n] -= 1 # Slightly modified prefix sum storage prefix_sum = [-1] * n # Number of 1's till i-1 cnt = 0 for i in range(n): prefix_sum[i] = cnt if (s[i] == '1'): cnt += 1 # Traversing over string considering # each position and finding bounds # and count using the inequalities for k in range(n): j = 1 while (j <= (n // x) and prefix_sum[k] + j <= cnt): # Calculating bounds for l and r l = (ones[prefix_sum[k] + j - 1] - k + 1) r = ones[prefix_sum[k] + j] - k l = max(l, j * (x + 1)) # If valid then add to answer if (l <= r): sum += r // j - (l - 1) // j j += 1 return sum # Driver code if __name__ == "__main__": S = "1111100000" print (countOfSubstrings(S)) # This code is contributed by chitranayal
C#
// C# program to count number of // subString under given condition using System; using System.Collections.Generic; class GFG{ // Function return count of such // substring static int countOfSubStrings(String s) { int n = s.Length; // Selection of adequate x value int x = (int)Math.Sqrt(n); // Store where 1's are located List<int> ones = new List<int>(); for(int i = 0; i < n; i++) { if (s[i] == '1') ones.Add(i); } // If there are no ones, // then answer is 0 if (ones.Count == 0) return 0; // For ease of implementation ones.Add(n); // Count storage int []totCount = new int[n * x + n]; int sum = 0; // Iterate on all k values less // than fixed x for(int k = 0; k <= x; k++) { // Keeps a count of 1's occured // during String traversal int now = 0; totCount[k * n]++; // Iterate on String and modify // the totCount for(int j = 1; j <= n; j++) { // If this character is 1 if (s[j-1] == '1') now++; int index = j - k * now; // Add to the readonly sum/count sum += totCount[index + k * n]; // Increase totCount at exterior // position totCount[index + k * n]++; } now = 0; totCount[k * n]--; for(int j = 1; j <= n; j++) { if (s[j-1] == '1') now++; int index = j - k * now; // Reduce totCount at index + k*n totCount[index + k * n]--; } } // Slightly modified prefix sum storage int []prefix_sum = new int[n]; for(int i = 0; i < n; i++) prefix_sum [i]= -1; // Number of 1's till i-1 int cnt = 0; for(int i = 0; i < n; i++) { prefix_sum[i] = cnt; if (s[i] == '1') cnt++; } // Traversing over String considering // each position and finding bounds // and count using the inequalities for(int k = 0; k < n; k++) { for(int j = 1; j <= (n / x) && prefix_sum[k] + j <= cnt; j++) { // Calculating bounds for l and r int l = ones[prefix_sum[k] + j - 1]- k + 1; int r = ones[prefix_sum[k] + j] - k; l = Math.Max(l, j * (x + 1)); // If valid then add to answer if (l <= r) { sum += r / j - (l - 1) / j; } } } return sum; } // Driver code public static void Main(String[] args) { String S = "1111100000"; Console.Write(countOfSubStrings(S)); } } // This code is contributed by Amit Katiyar
Javascript
<script> // Javascript program to count number of // substring under given condition // Function return count of such // substring function countOfSubstrings(s) { var n = s.length; // Selection of adequate x value var x = parseInt(Math.sqrt(n)); // Store where 1's are located var ones = []; for (var i = 0; i < n; i++) { if (s[i] == '1') ones.push(i); } // If there are no ones, // then answer is 0 if (ones.length == 0) return 0; // For ease of implementation ones.push(n); // Count storage var totCount = Array(n * x + n).fill(0); var sum = 0; // Iterate on all k values less // than fixed x for (var k = 0; k <= x; k++) { // Keeps a count of 1's occured // during string traversal var now = 0; totCount[k * n]++; // Iterate on string and modify // the totCount for (var j = 1; j <= n; j++) { // If this character is 1 if (s[j - 1] == '1') now++; var index = j - k * now; // Add to the final sum/count sum += totCount[index + k * n]; // Increase totCount at exterior // position totCount[index + k * n]++; } now = 0; totCount[k * n]--; for (var j = 1; j <= n; j++) { if (s[j - 1] == '1') now++; var index = j - k * now; // Reduce totCount at index + k*n totCount[index + k * n]--; } } // Slightly modified prefix sum storage var prefix_sum = Array(n).fill(-1); // Number of 1's till i-1 var cnt = 0; for (var i = 0; i < n; i++) { prefix_sum[i] = cnt; if (s[i] == '1') cnt++; } // Traversing over string considering // each position and finding bounds // and count using the inequalities for (var k = 0; k < n; k++) { for (var j = 1; j <= parseInt(n / x) && prefix_sum[k] + j <= cnt; j++) { // Calculating bounds for l and r var l = ones[prefix_sum[k] + j - 1] - k + 1; var r = ones[prefix_sum[k] + j] - k; l = Math.max(l, j * (x + 1)); // If valid then add to answer if (l <= r) { sum += parseInt(r / j) - parseInt((l - 1) / j); } } } return sum; } var S = "1111100000"; document.write( countOfSubstrings(S)); </script>
25
Complejidad del tiempo:
Espacio Auxiliar: O(N 3/2 )