lundi 5 janvier 2015

Efficient algorithm to count number of substrings divisible by 3


Given a string of decimal digits, I have to find the number of all substrings divisible by 3 in the range L to R [both inclusive], where L & R are index[1-based] of the specified string

string length <= 100000


I've tried the Naive approach of iterating over all possible substrings & obtaining the answer, but that is not fast enough, especially for multiple pairs L & R.


Then I tried a DP approach. I can obtain all possible substrings divisible by 3 in the whole string, i.e. I'm unable to code the DP solution that gives result for given range.

DP Solution that I tried (not completely sure about It):



for(i=0 ; i<n ; i++) {
for(j=0 ; j<3 ; j++) {
dp[i][j]=0 ;
}
int curr = (input[i]-'0')%3 ;
dp[i][curr]++ ;
if(i) {
for(j=0 ; j<3 ; j++) {
if(curr % 3 == 0) { dp[i][j] += dp[i-1][j]; }
if(curr % 3 == 1) { dp[i][j] += dp[i-1][(j+2)%3]; }
if(curr % 3 == 2) { dp[i][j] += dp[i-1][(j+1)%3]; }
}
}
}
long long sum = 0;
for(i=0 ; i<n ; i++) { sum += dp[i][0] ; }


Can this solution be modified to give results for given range [L,R] ?


After searching alot, I learnt that range queries problems are solved by Segment Tree, but I'm unsure as how Segment Tree + Lazy Propagation can help in this question.


So what is a performant way to count all substrings divisible by 3 in the range L to R [both inclusive]?


EDIT:

Input: First Line contains the given string. Lines after that contain two integers denoting L and R respectively, where both L and R are index(1-based) of string.



Input:

301524 1 2 4 6 3 5


Output:

3 1 1


Explanation:

When L=1 & R=2 we get 3 possible substrings, {3}, {0}, {30} & all these when considered as a decimal number are divisible by 3. Hence the output.

When L=4 & R=6 we get 6 possible substrings, {5} , {52}, {524}, {2}, {24}, {4} & out of these only {24} is divisible by 3.



Repetitions in substrings like 3333 count multiple times, so for L=1 to R=4 the answer would be 10, since we have four times 3, three times 33, two times 333 and one time 3333 (all divisible by 3).





Aucun commentaire:

Enregistrer un commentaire