Rabin-Karp String Matching is not matching - c++

I've been working on a Rabin-Karp string matching function in C++ and I'm not getting any results out of it. I have a feeling that I'm not computing some of the values correctly, but I don't know which one(s).
Prototype
void rabinKarp(string sequence, string pattern, int d, int q);
Function Implementation
void rabinKarp(string sequence, string pattern, int d, int q)
{
//d is the |∑|
//q is the prime number to use to lessen spurious hits
int n = sequence.length(); //Length of the sequence
int m = pattern.length(); //Length of the pattern
double temp = static_cast<double> (m - 1.0);
double temp2 = pow(static_cast<double> (d), temp); //Exponentiate d
int h = (static_cast<int>(temp2)) % q; //High Order Position of an m-digit window
int p = 0; //Pattern decimal value
int t = 0; //Substring decimal value
for (int i = 1; i < m; i++) { //Preprocessing
p = (d*p + (static_cast<int>(pattern[i]) - 48)) % q;
t = (d*t + (static_cast<int>(sequence[i])-48)) % q;
}
for (int s = 0; s < (n-m); s++) { //Matching(Iterate through all possible shifts)
if (p == t) {
for (int j = 0; j < m; j++) {
if (pattern[j] == sequence[s+j]) {
cout << "Pattern occurs with shift: " << s << endl;
}
}
}
if (s < (n-m)) {
t = (d*(t - ((static_cast<int>(sequence[s+1]) - 48)*h)) + (static_cast<int>(sequence[s + m + 1]) - 48)) % q;
}
}
return;
}
In my function call I pass 2359023141526739921 as the sequence, 31415 as the pattern, 10 as the radix, and 13 as the prime. I expect there to be one actual match and one spurious hit, but I never get the output statement from the matching part of the function. What am I doing wrong?
Thanks in Advance, Madison

The big gotcha in coding the Rabin Karp is the modulo operator. When two numbers X and Y are congruent modulo Q then (X % Q) should equal (Y % Q) but on the C++ compiler you're using they will only be equal if X and Y are both positive or both negative. If X is positive and Y is negative then (X % Q) will be positive and (Y % Q) will negative. In fact (X % Q)-Q == (Y % Q) in this case.
The work around is to check for negative values after each modulo and if there are any to add q to the variable, so your preprocessing loop becomes :
p = (d*p + pattern[i]) % q;
if ( p < 0 ) p += q;
t = (d*t + sequence[i]) % q;
if ( t < 0 ) t += q;
t in the main loop needs to have a similar check added.

Unless you've redefined ^, it is computing xor, not exponentiation. Also, you should be careful about overflowing the maximum value of an int before you perform %.

Related

STRONGN Strong Number (Special Numbers Series #2) word problem on Code Wars

Strong number is the number that the sum of the factorial of its digits is equal to number itself.
For example: 145, since
1! + 4! + 5! = 1 + 24 + 120 = 145
Here is my code, It passes most of the test except one test
#include <string>
using namespace std;
string strong_num (int number )
{
int sum = 0;
while(number != 0) {
int last = number % 10;
number /= 10;
sum+= last * (last-1);
}
if(sum == number)
return "STRONG!!!!";
else
return "Not Strong !!";
}
What is wrong with my code?
I'm surprised you're passing any test cases at all. For one thing, you are destroying number before you compare it to sum, and for another your logic is flawed.
Try this:
int factorial (int x)
{
int result = 1;
while (x > 1)
{
result *= x;
x--;
}
return result;
}
string strong_num (int number)
{
int sum = 0;
int x = number;
while (x != 0) {
int digit = x % 10;
sum += factorial (digit);
x /= 10;
}
if (sum == number)
return "STRONG!!!!";
else
return "Not Strong !!";
}
Live demo
Replace int by long long to be able to test larger numbers.
There are two problems:
first - you are changing the value of number before comparing it to sum,
second - the thing you used last * (last-1) is not a definition of factorial, the definition of factorial is factorial(x) = 1 * 2 * 3 * ... * x
int factorial (int x) {
if(x < 2) return 1;
return x * factorial(x - 1);
}
string strong_num (int number)
{
int sum = 0;
int x = number;
while (x != 0) {
int last = x % 10;
sum += factorial (last);
x /= 10;
}
if (sum == number)
return "STRONG!!!!";
else
return "Not Strong !!";
}

Floating point exception with big numbers and inaccurate results when changing integers to longs

I was given this problem which gives you 2 integers n and m, n representing the number of figures of the second number, and the second number is a binary number. For example:
n= 2
m= 11
After figuring out the binary number, you have to get that number to be 0. You are only allowed to substract 1 from the binary or divide by two. For example, in this case it would be:
3->2->1 so the result is 2 since there were 2 operations made
My program does work and displays the binary number and the number of operations. But when given big numbers, it throws floating point exception. My theory is that it is because ints are too short. But when I change them to longs, it throws a completely inaccurate result.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m, g, l, f, x, k, w;
cin >> n >> m;
g = pow(10, n);
k = pow(2, n - 1);
for (int i = 1; i <= n; i++)
{
l = m % g;
f = l / (g / 10);
if (f == 1)
{
x += k;
}
k /= 2;
g /= 10;
}
cout << x << endl;
while (x != 1)
{
if (x % 2 == 0)
{
x /= 2;
}
else
{
x -= 1;
}
w++;
}
cout << w;
return 0;
}

From recursive algorithm to an iterative one

I have to convert this recursive algorithm into an iterative one:
int alg(int A[], int x, int y, int k){
int val = 0;
if (x <= y){
int z = (x+y)/2;
if(A[z] == k){
val = 1;
}
int a = alg(A,x,z-1,k);
int b;
if(a > val){
b = alg(A,z+1,y,k);
}else{
b = a + val;
}
val += a + b;
}
return val;
}
I tried with a while loop, but I can't figure out how I can calculate "a" and "b" variables, so I did this:
int algIterative(int A[], int x, int y, int k){
int val = 0;
while(x <= y){
int z = (x+y)/2;
if(A[z] == k){
val = 1;
}
y = z-1;
}
}
But actually I couldn't figure out what this algorithm does.
My questions are:
What does this algorithm do?
How can I convert it to iterative?
Do I need to use stacks?
Any help will be appreciated.
I am not sure that alg computes anything useful.
It processes the part of the array A between the indexes x and y, and computes a kind of counter.
If the interval is empty, the returned value (val) is 0. Otherwise, if the middle element of this subarray equals k, val is set to 1. Then the values for the left and right subarrays are added and the total is returned. So in a way, it counts the number of k's in the array.
But, if the count on the left side is found to be not larger than val, i.e. 0 if val = 0 or 0 or 1 if val = 1, the value on the right is evaluated as the value on the left + val.
Derecursivation might be possible without a stack. If you look at the sequence of subintervals that are traversed, you can reconstruct it from the binary representation of N. Then the result of the function is the accumulation of partials results collected along a postorder process.
If the postorder can be turned to inorder, this will reduce to a single linear pass over A. This is a little technical.
A simple way could be smt like this with the aid of a two dimensional array:
int n = A.length;
int[][]dp = new int[n][n];
for(int i = n - 1;i >= 0; i--){
for(int j = i; j < n; j++){
// This part is almost similar to the recursive part.
int z = (i+j)/2;
int val = 0;
if(A[z] == k){
val = 1;
}
int a = z > i ? dp[i][z - 1] : 0;
int b;
if(a > val){
b = (z + 1 <= j) ? dp[z + 1][j] : 0;
}else{
b = a + val;
}
val += a + b;
dp[i][j] = val;
}
}
return dp[0][n - 1];
Explanation:
Notice that for i, it is decreasing, and j, it is increasing, so, when calculate dp[x][y], you need dp[x][z - 1] (with z - 1 < j) and dp[z + 1][j] (with z >= i), and those values should already be populated.

Modular multiplicative inverse function doesn't work for negative numbers

I have the function below to calculate the modular multiplicative inverse of a number n given the modulo number p.
int modInverse(int n, int p) {
n %= p;
for(int x = 1; x < p; x++) {
if((n*x) % p == 1) return x;
}
}
If n is positive, it wokrs fine, but if n is negative it gives always 0.
How can I fix it?
Multiplicative inverse of x mod n: x^-1 mod n, is the number that must be multiplied by x to get 1 mod n
e.g. 3^-1 mod 7 = 5, since 3 * 5 = 1 mod 7
example code:
int modulo(int n, int p)
{
int r = n%p;
if(((p > 0) && (r < 0)) || ((p < 0) && (r > 0)))
r += p;
return r;
}
int modInverse(int n, int p) {
n = modulo(n, p);
for(int x = 1; x < p; x++) {
if(modulo(n*x, p) == 1) return x;
}
return 0;
}
int main(void)
{
int r;
r = modInverse(-25, 7);
return 0;
}
if you wanted a quotient and a remainder:
void divmod(int n, int p, int &q, int &r)
{
q = n/p;
r = n%p;
if(((p > 0) && (r < 0)) || ((p < 0) && (r > 0))){
q -= 1;
r += p;
}
}
Besides unnecessary iterations, the method you are using has a O(p) complexity. You may want to use the Extended Euclidean Algorithm with a O(log(p)) complexity. Anyway, answering to your question and the way you're doing it, I'd suggest you try this approach, which reduces the number of iterations: (Java)
int calculateInverse2(int a, int zp) {
for (int i = (int) Math.ceil((zp-1)/a); i < zp; i++) {
if (Math.floorMod(a*i,zp) == 1) return i;
}
return -1;
}
Related to negative values in modulo operation, depends upon the language. Try to implement a method which sums certain times p to establish the number within the integer ring.
Example:
(-7)mod(2) => (-7+2)mod(2) => (-7+2+2)mod(2) => (-7+2+2+2)mod(6) => (-7+2+2+2+2)mod(6) => (1)mod(7)=1
Easy to compute.

How to find the sum of elements on even position?

How to find the sum of elements on even position without usage of arrays etc, only normal operations?
For example:
159
Sum = 5.
159120
Sum = 5+1+0 = 6.
My work:
int sumofdigits(int x)
{
int sum = 0;
while(x > 0){
if (x % 100 != 0)
sum += x % 100;
x /= 100;
}
return sum;
}
Since you're counting "even" digits from the left, you first need to count the number of digits in order to know whether the least significant digit is even or not:
int sumOfEvenDigits(int x)
{
// First, count the number of digits
int digitCount = 0;
int tmp = x;
while(tmp) {
tmp /= 10;
digitCount++;
}
// If the number of digits is odd, throw away the least significant digit
if(digitCount % 2 == 1)
x /= 10;
// Keep adding the least significant digit, and throwing away two digits until you're done.
int sum = 0;
while(x){
sum += x % 10;
x /= 100;
}
return sum;
}
int accumulateIfEvenPos(int num, int pos) {
if (num == 0) return 0;
int digit = num % 10;
int next = num / 10;
return pos & 1 ? digit + accumulateIfOdd(next, ++pos) : accumulateIfOdd(next, ++pos);
}
You call it with pos 1 initially - demo here.
Well simple modification should do the trick.
int main()
{
int x = 1549;
//Get the number of digits
int length = snprintf(NULL, 0, "%i", x);
int sum = 0;
while(x > 0){
if (x % 100 != 0) {
//check if the number of digits is even to start from the last digit
if (length % 2 == 0) {
sum += x % 10;
x /= 10;
}
else {
x /= 10;
sum += x % 10;
}
x /= 10;
}
}
cout << sum << endl;
return 0;
}
EDIT: Solved the problem/bug in the algorithm. This might not be the best answer but I didn't want to completely write a different one(than the answer before edit).
You will need to have an index variable that keeps track of the position:
unsigned int digit_position = 0;
while (x > 0)
{
unsigned int digit_value = x % 10;
if (digit_position is even)
{
// Add digit_value to sum
}
// Shift value right one digit
x /= 10;
++digit_position;
}
There may be other methods using a position variable and the pow() function. But that is left as an exercise for the reader.