Segmentation Fault in Suffix Array Implementation - c++

when I run the following code written to implement the suffix array algorithm, I get a segmentation fault. Can anyone please help me in solving it? I think the issue is with the while since cout in all other places work properly
Following is the code is used
vector<int> suffixArray(string s, int n)
{
vector<int> p(n); // Indexes
vector<int> c(n); // Classes
{
vector<pair<char, int>> a(n);
for (int i = 0; i < n; i++)
{
a[i] = {s[i], i};
}
sort(a.begin(), a.end());
for (int i = 0; i < n; i++)
p[i] = a[i].second;
c[p[0]] = 0;
for (int i = 1; i < n; i++)
{
if (a[i].first == a[i - 1].first)
{
c[p[i]] = c[p[i - 1]];
}
else
{
c[p[i]] = c[p[i - 1]] + 1;
}
}
}
int k = 0;
while (pow(2, k) < n)
{
vector<pair<pair<int, int>, int>> a;
for (int i = 0; i < n; i++)
{
a[i] = {{c[i], c[(int)(i + pow(2, k)) % n]}, i};
}
sort(a.begin(), a.end());
for (int i = 0; i < n; i++)
p[i] = a[i].second;
c[p[0]] = 0;
for (int i = 1; i < n; i++)
{
if (a[i].first == a[i - 1].first)
{
c[p[i]] = c[p[i - 1]];
}
else
{
c[p[i]] = c[p[i - 1]] + 1;
}
}
k++;
}
return p;
}
Thank You

Related

vector subscript out of range line 1475

I can't figure out where the error is.
vector<int> subVector(const vector<int>& a, const vector<int>& b) {
vector<int> res;
res = a;
for (int i = 0; i < res.size() && i < b.size(); i++)
{
if (res[i] < b[i])
{
int k = 1;
while (res[i + k] == 0)
k++;
for (int j = 0; j < k; j++)
{
res[i + j + 1]--;
res[i + j] += 10;
}
}
res[i] -= b[i];
}
return res;
}
vector<int> addVector(const vector<int>& a, const vector<int>& b) {
vector<int> ans;
ans.resize(max(a.size(), b.size()) + 1);
for (int i = 0; i < a.size(); i++)
ans[i] = a[i];
for (int i = 0; i < b.size(); i++)
{
ans[i] += b[i];
ans[i + 1] += ans[i] / 10;
ans[i] = ans[i] % 10;
int k = i + 1;
while (ans[k] >= 10)
{
ans[k + 1] += ans[k] / 10;
ans[k] %= 10;
k++;
}
}
return ans;
}
vector subscript out of range line 1475 and error debug.
I tried to fix it but couldn't. I can't understand how this error works.
Wherever you are accessing a vector with the [] operator, and inside it, you are doing some arithmetic operation, you need to make sure that the result is not exceeding the vector boundaries.
For example:
vector<int> subVector(const vector<int>& a, const vector<int>& b) {
vector<int> res;
res = a;
for (int i = 0; i < res.size() && i < b.size(); i++) <--- 'i' is promised to be in 'res' boundry
{
if (res[i] < b[i])
{
int k = 1;
while (res[i + k] == 0) <--- 'i+1' can exceeds the 'res' boundry
// Rest of the code ...
This is just one example. You are doing it all over your code.

/bin/run.sh: line 4: 18 Segmentation fault (core dumped) ./exe

#include <bits/stdc++.h>
using namespace std;
int solve(int A, vector<int> &B) {
vector<int> pre(A);
vector<int> suff(A);
vector<int> p;
vector<int> s;
int sum = 0;
int ans = 0;
for (int i = 0; i < A; i++) {
sum = sum + B[i];
}
if (sum % 3 != 0)
return 0;
sum = sum / 3;
for (int i = 0; i < A; i++) {
if (i == 0) {
pre[i] = B[i];
if (pre[i] == sum) {
p.push_back(i);
}
continue;
}
pre[i] = B[i] + pre[i - 1];
if (pre[i] == sum) {
p.push_back(i);
}
}
for (int i = A - 1; i >= 0; i--) {
if (i == A - 1) {
suff[A - 1] = B[A - 1];
if (suff[i] == sum) {
s.push_back(i);
}
continue;
}
suff[i] = B[i] + pre[i + 1];
if (suff[i] == sum) {
s.push_back(i);
}
}
for (int i = 0; i < p.size(); i++) {
for (int j = s.size(); j >= 0; j++) {
if (s[j] > p[i] + 1) {
ans++;
}
}
}
return ans;
}
int main() {
int A = 5;
vector<int> B = {1, 2, 3, 0, 3};
cout << solve(5, B);
return 0;
}
The code keeps getting dumped at pre[i]=B[i]. The code is very simple for counting the number of ways to split all the elements of the array into 3 contiguous parts so that the sum of elements in each part is the same.
I just made a prefix and suffix sum array.

Can't count all the inversions while implementing mergesort code

I've been trying to figure out how to get this code to count all inversions, but just can't seem to put my finger on it. To my understanding this code should count all of the inversions, but it fails many test cases, nudges in the right directions, or even the whole fix would be appreciated.
Code:
int countInversion(vector<int>& v, int& inv) {
if(v.size() > 1) {
vector<int> left(v.begin(), v.begin() + v.size()/2);
vector<int> right(v.begin() + v.size()/2, v.end());
countInversion(left, inv);
countInversion(right, inv);
int l = 0; int r = 0;
for(int i = 0; i < v.size(); i++) {
if(r >= right.size() || (l < left.size() && left[l] < right[r])) {
v[i] = left[l++];
} else {
if(right[r] < left[l]) inv += left.size() - l;
v[i] = right[r++];
}
}
} return inv;
}
The code that did work (I found it on the internet) has very low
readability can someone help me understand it? and more importantly, point to me what my code exactly missed on and if it's possible to rectify my code to count properly? Thank you!
Code 2:
long long ans = 0;
void mergei(int a[],int i,int j) {
int ni = ((i+j)/2) + 1, nj = j + 1;
int s = i;
int* arr = new int [j - i + 1];
j = ni;
int k = 0;
while(i < ni && j < nj) {
if(a[i] <= a[j]) {
arr[k] = a[i++];
} else {
arr[k] = a[j++];
ans += (ni - i);
} k++;
}
for(; i < ni; i++, k++) arr[k] = a[i];
for(; j < nj; j++, k++) arr[k] = a[j];
for(k = 0; s < nj; s++, k++) a[s] = arr[k];
delete [] arr;
}
void m_sort(int a[],int i,int j) {
if(i < j) {
m_sort(a, i, (i+j)/2);
m_sort(a, ((i+j)/2) + 1, j);
mergei(a, i, j);
}
}
I finally found a way to solve it using my code, I was sure some changes to the if else block or how I added the inversions would fix it, it just had to, that's the whole point of mergesort, that's why I was adamant about solving it this way, instead of just using another code. The issue was; I was doing left[l] < right[r] which doesn't matter for merging if it's left or right, but does for inversions, just had to change it to left[l] <= right[r].
long countInversions(vector<int>& arr, long& inv) {
if(arr.size() > 1) {
vector<int> left(arr.begin(), arr.begin() + arr.size()/2);
vector<int> right(arr.begin() + arr.size()/2, arr.end());
countInversions(left, inv);
countInversions(right, inv);
int l = 0; int r = 0;
for(int i = 0; i < arr.size(); i++) {
if(r >= right.size() || (l < left.size() && left[l] <= right[r])) {
arr[i] = left[l++];
// inv += r;
} else {
arr[i] = right[r++];
inv += left.size() - l;
}
}
} return inv;
}
A slightly better and more readable code would be:
long countInversions(vector<int>& v) {
if(v.size() <= 1) return 0;
vector<int> left(v.begin(), v.begin() + v.size()/2);
vector<int> right(v.begin() + v.size()/2, v.end());
long inv = countInversions(left) + countInversions(right);
int l = 0, r = 0;
for(int i = 0; i < v.size(); i++) {
if(r >= right.size() || (l < left.size() && left[l] <= right[r])) {
v[i] = left[l++];
// inv += r;
} else {
v[i] = right[r++];
inv += left.size() - l;
}
}
return inv;
}

vector subscription out of range c++

I am working on a program that reads integers from file, stores it in vector and use count sort to sort the integers and write them in new file. My problem ocurs when i run Countsort function, the breakpoint happens at this for loop:
for (int i = 0; i < C.size(); i++) {
C[A[i]] = C[A[i]] + 1;
}
my code looks like this:
//COUNT SORT
void countsort() {
int max = A[0];
for (int i = 1; i < A.size(); i++) {
if (A[i] > max) {
max = A[i];
}
}
//cout << "NAJVECJE STEVILO JE: " << max << endl; SAMO ZA TEST
vector<int> C(max + 1);
vector<int> B(A.size());
for (int i = 0; i < C.size(); i++) {
C[A[i]] = C[A[i]] + 1;
}
for (int i = 1; i < C.size(); i++) {
C[i] = C[i] + C[i + 1];
}
for (int i = C.size() - 1; i >= 0; i--) {
B[C[A[i]] - 1] = A[i];
C[A[i]] = C[A[i]] - 1;
}
for (int i = 0; i < A.size(); i++) {
A[i] = B[i];
}
}
First you zero whole C vector
for (int i = 0; i < C.size(); i++)
{
C[i] = 0;
}
In second loop you may not change C[0] so it will remain 0
for (int i = 0; i < A.size(); i++)
{
C[A[i]] = C[A[i]] + 1;
}
In third loop in my analysis you never change C[0]
for (int i = C.size() - 1; i > 0; i-- )
{
C[i] = C[i] + C[i - 1];
}
In last loop
for (int i = A.size() - 1; i >= 0; i--)
{
B[C[A[i]] - 1] = A[i];
C[A[i]] = C[A[i]] - 1;
cout << B[i] << " ";
}
A[i] may equal 0, so C[A[i]] is C[0] and it might equal 0 from analysis of previous loops. When you subtract 1 from it, you'll end up with B[-1] which breaks your code.
Before you write something to B vector you should probably initialize it firt like you did with C.
B = vector<int>(A.size());
Also I don't see any point of printing B[i] as it may not be assigned any value when you print it.
Edit #1
Your loop is not correct. Take a look at this:
for (int i = 1; i < C.size(); i++) {
C[i] = C[i] + C[i - 1];
}
Edit #2
Try this code.
vector<int> A, B;
//COUNT SORT
void countsort() {
int max = A[0];
for (int i = 1; i < A.size(); i++) {
if (A[i] > max) {
max = A[i];
}
}
vector<int> C(max + 1);
B = vector<int>(A.size());
for (int i = 0; i < C.size(); i++) C[i] = 0;
for (int i = 0; i < A.size(); i++) C[A[i]] = C[A[i]] + 1;
for (int i = 1; i < C.size(); i++) C[i] = C[i] + C[i - 1];
for (int i = A.size() - 1; i >= 0; i--) {
B[C[A[i]] - 1] = A[i];
C[A[i]] = C[A[i]] - 1;
}
for (int i = 0; i < B.size(); i++) cout << B[i];
}
int main(void) {
A.push_back(1);
A.push_back(2);
A.push_back(3);
A.push_back(4);
A.push_back(2);
A.push_back(2);
A.push_back(1);
countsort();
}

How to get BucketSort algorithm working?

I am trying to create a bucketsort algorithm in C++, but it is not working at all. Every run, it adds many new numbers, often very large, such as in the billions, into the array. Does anyone know why this is? Here is the code - (Note that I am passing in an array of size 100, with random numbers from 0 to ~37000, and that the insertion sort function is fully functional and tested multiple times)
It would be greatly appreciated if someone could point out what's wrong.
void bucketSort(int* n, int k)
{
int c = int(floor(k/10)), s = *n, l = *n;
for(int i = 0; i < k; i++) {
if(s > *(n + i)) s = *(n + i);
else if(l < *(n + i)) l = *(n + i);
}
int bucket[c][k + 1];
for(int i = 0; i < c; i++) {
bucket[i][k] = 0;
}
for(int i = 0; i < k; i++) {
for(int j = 0; j < c; j++) {
if(*(n + i) >= (l - s)*j/c) {
continue;
} else {
bucket[j][bucket[j][k]++] = *(n + i);
break;
}
}
}
for(int i = 0; i < c; i++) {
insertionSort(&bucket[i][0], k);
}
}
This line does not compile. int bucket[c][k + 1];
I think the problem is with you bucket indices. This part here
for(int j = 0; j < c; j++) {
if(*(n + i) >= (l - s)*j/c) {
continue;
} else {
bucket[j][bucket[j][k]++] = *(n + i);
break;
}
}
does not do the equivalent of:
insert n[i] into bucket[ bucketIndexFor( n[i]) ]
First it gets the index off by one. Because of that it also misses the break for the numbers for the last bucket. There is also a small error introduced because the index calculation uses the range [0,l-s] instead of [s,l], which are only the same if s equals 0.
When I write bucketIndex as:
int bucketIndex( int n, int c, int s, int l )
{
for(int j = 1; j <= c; j++) {
if(n > s + (l-s)*j/c) {
continue;
} else {
return j-1;
}
}
return c-1;
}
and rewrite the main part of your algorithm as:
std::vector< std::vector<int> > bucket( c );
for(int i = 0; i < k; i++) {
bucket[ bucketIndex( n[i], c, s, l ) ].push_back( n[i] );
}
I get the items properly inserted into their buckets.