I was trying to implement suffix tree using c++ by looking at some examples online. I am running into pointer issue and I am not able to fix it. Any help is greatly appreciated.
/*
* Implement suffix array to print the maximum suffix substring in a string
* Algorithm:
* Build a suffix tree and find the lowest node with multiple children
*
*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <ctype.h>
using namespace std;
struct node{
char ch;
node* next[26];
int treeHeight;
int childCount;
int end = 0;
};
void insertSuffixIntoTree(node*& root, string suffix){
if (suffix.size() == 0){
return;
}
char c = suffix[0];
int index = tolower(c) - 'a';
if (root->next[index] == NULL){
root->next[index] = new node();
for (int k = 0; k < 26; k++){
root->next[index]->next[k] = NULL;
}
root->next[index]->ch = tolower(c);
if (suffix.size() == 1){
root->next[index]->end = 1;
}
}
suffix.erase(suffix.begin());
insertSuffixIntoTree(root->next[index], suffix);
}
void buildSuffixTree(node* root, string str){
if (root == NULL) cout << "CRAP" << endl;
for (int i = str.size() - 1; i >= 0; i--){
string suffix = str.substr(i);
cout << "suffix is " << suffix << endl;
insertSuffixIntoTree(root, suffix);
}
}
void printSuffixTree(node* root, string str){
if (root->end){
cout << str << endl;
return;
}
for (int i = 0; i<26; i++){
while (root->next[i]){
str += root->ch;
return printSuffixTree(root->next[i],str);
}
}
}
int main() {
string str;
node* suffixRoot = new node();
suffixRoot->ch = ' ';
for (int i = 0; i < 26; i++){
suffixRoot->next[i] = NULL;
}
cout << "enter the string" << endl;
cin >> str;
buildSuffixTree(suffixRoot, str);
//string result = findMaxSuffix(suffixRoot,str);
//cout<<"result is "<<result<<endl;
string result = "";
printSuffixTree(suffixRoot,result);
getchar();
return 0;
}
The error is happening at insertIntoSuffixTree method inside buildSuffixTree method. My understanding is I am loosing my pointer address I started with. Any idea on how to get around this issue?
Sorry for any inconvenience. I fixed the code as seen below:
/*
* Implement suffix array to print the maximum suffix substring in a string
* Algorithm:
* Build a suffix tree and find the lowest node with multiple children
*
*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <ctype.h>
using namespace std;
struct node{
char ch;
node* next[26];
int treeHeight;
int childCount;
int end = 0;
};
void insertSuffixIntoTree(node* root, string suffix){
if (suffix.size() == 0){
return;
}
char c = suffix[0];
int index = tolower(c) - 'a';
if (root->next[index] == NULL){
root->next[index] = new node();
for (int k = 0; k < 26; k++){
root->next[index]->next[k] = NULL;
}
root->next[index]->ch = tolower(c);
if (suffix.size() == 1){
root->next[index]->end = 1;
}
}
suffix.erase(suffix.begin());
insertSuffixIntoTree(root->next[index], suffix);
}
void buildSuffixTree(node* root, string str){
if (root == NULL) cout << "CRAP" << endl;
for (int i = str.size() - 1; i >= 0; i--){
string suffix = str.substr(i);
cout << "suffix is " << suffix << endl;
insertSuffixIntoTree(root, suffix);
}
}
bool checkEmptyVector(node * leaf){
for (int i = 0; i < 26; i++){
if (leaf->next[i] != NULL){
return false;
}
}
return true;
}
void printSuffixTree(node* root, string str){
if (root->end){
cout << str << endl;
}
if (checkEmptyVector(root)){
return;
}
for (int i = 0; i<26; i++){
//cout << "inside for loop, i is " << i << endl;
while (root->next[i]){
str += root->next[i]->ch;
printSuffixTree(root->next[i],str);
break;
}
}
}
int main() {
string str;
node* suffixRoot = new node();
suffixRoot->ch = ' ';
for (int i = 0; i < 26; i++){
suffixRoot->next[i] = NULL;
}
cout << "enter the string" << endl;
cin >> str;
buildSuffixTree(suffixRoot, str);
//string result = findMaxSuffix(suffixRoot,str);
//cout<<"result is "<<result<<endl;
string result = "";
printSuffixTree(suffixRoot,result);
getchar();
return 0;
}
Related
Trying to implement a hash table with linear probing for a project but I am running into a few issues, where I think one of them is the main culprit.
For starters, after compiling the code, if I were to run the program 10 times in a row, I would experience a segmentation fault: 11 around 2/3 of the time.
When the code does actually run, it seems to "mostly" work. indicies 9500-10000 are perfect with all slots filled. But when continuing down(9000-9500), more than 10 NULL spaces are seen and there are some slots filled with bogus values, ie. value > 100,000.
I am using a dataset of 10,000 integers from a csv file all with values < 100,000. I was going to try to debug this using GDB and core however my computer isn't too pleased with my installing it at the moment.
#ifndef HASHLINEAR_HPP
#define HASHLINEAR_HPP
struct node{
int key;
};
class HashLinear{
struct node** table;
int tableSize;
int numCollisions = 0;
public:
HashLinear(int bsize);
void insert(int key);
unsigned int hashFunction(int key);
int search(int key);
int getCollisions();
void printTable();
};
#endif
#include "hashlinear.hpp"
#include <iostream>
using namespace std;
HashLinear::HashLinear(int bsize){
this->tableSize = bsize;
table = new node*[tableSize];
for(int i = 0; i < tableSize; i++){
table[i] = NULL;
}
}
int HashLinear::getCollisions(){
return numCollisions;
}
unsigned int HashLinear::hashFunction(int key){
return key % tableSize;
}
void HashLinear::insert(int key){
node* newNode = new node;
newNode->key = key;
int index = hashFunction(key);
while(table[index] != NULL && table[index]->key != key){
numCollisions++;
index = (index + 1) % tableSize;
}
table[index] = newNode;
}
int HashLinear::search(int key){
int value = hashFunction(key);
int num = 0;
while(table[value] != NULL){
num = 0;
if(num++ > tableSize){
break;
}
if(table[value]->key == key){
return value;
}
value++;
value %= tableSize;
}
return -1;
}
void HashLinear::printTable(){
for(int i = 0; i < tableSize; i++){
cout << i << " || ";
if(table[i] == NULL){
cout << "NULL" << endl;
}
else{
cout << table[i]->key << endl;
}
}
}
#include "hashlinear.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <stdlib.h>
#include <chrono>
using namespace std;
int main(){
//******Read in data******//
int testData[10000];
float insertTime[100];
float searchTime[100];
int index = 0;
string line, temp, word;
ifstream inputFile;
inputFile.open("dataSetA-updatedhashlinear.csv");
if(inputFile.fail()){
cout << "Could not open data." << endl;
return -1;
}
else{
while(inputFile >> temp){
getline(inputFile, temp);
stringstream inStream(temp);
while(getline(inStream, word, ',')){
testData[index] = stoi(word);
index++;
}
}
inputFile.close();
}
//******Read in data******//
//cout << "Printing random data in range of 0 ~ 10: " << testData[rand() % 10 + 0] << endl;
//******Insert/Search data in Linked List******//
HashLinear table(10009);
int hashIndex = 0;
int insertTimeIndex = 0;
int searchTimeIndex = 0;
int num = 0;
int upperIndex = 99;
while(hashIndex < 10009){
//Block for 100 insertions
auto insertionStart = chrono::steady_clock::now();//Insert time start
for(int i = hashIndex; i < upperIndex; i++){ //Keep track of current index as well as an upper index to control amount of inserts
table.insert(testData[i]);
hashIndex++;
}
auto insertionEnd = chrono::steady_clock::now();
insertTime[insertTimeIndex] = chrono::duration_cast<chrono::microseconds>(insertionEnd - insertionStart).count() / 100.0;//Insert time end
insertTimeIndex++;
//Block for 100 insertions
//Block for 100 searches
num = 0;
auto searchStart = chrono::steady_clock::now();//Search time start
while(num < 100){ //Do 100 random searches from 0 index to upperindex
srand((unsigned)time(0));
int searchNode = table.search(testData[rand() % upperIndex + 0]);
num++;
}
auto searchEnd = chrono::steady_clock::now();
searchTime[searchTimeIndex] = chrono::duration_cast<chrono::microseconds>(searchEnd - searchStart).count() / 100.0;//Search time end
searchTimeIndex++;
//Block for 100 searches
upperIndex += 100;
}
//******Insert/Search data in Linked List******//
//******TESTING******//
table.printTable();
cout << "Search time: " << searchTime[20] << endl;
cout << "Insert time: " << insertTime[20] << endl;
cout << "Collisons: " << table.getCollisions() << endl;
int testIndex = table.search(34262);
cout << "Index of 34262: " << testIndex << endl;
//******TESTING******//
}
So after some more debugging I figured out I am just slow. I was iterating 100 times past the end of the testData array creating bogus values and making the hash table not fill correctly.
I need to build a code where it takes a 2d array of char and checks if its palindrome the second function uses the first one to see how many arrays are palindrome my issue with the code is that every time I get count is 0; I know the issue is in the second function but don't know where
#include <iostream>
using namespace std;
int CountPal(char M[][5], int rows);
int pal(char* S) {
char *p, *start, flag = 1;
p = S;
while(*p != NULL) {
++p;
}
--p;
for(start = S; p >= start && flag;) {
if(*p == *start) {
--p;
start++;
} else
flag = 0;
}
}
int main() {
int x;
cout << "please enter the number of rows " << endl;
cin >> x;
char M[5][5];
cout << "before test" << endl;
cout << CountPal(M, x) << endl;
cout << "After test" << endl;
system("pause");
}
int CountPal(char M[][5], int rows) {
int count = 0;
cout << "please enter the string " << endl;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < 5; j++) {
cin >> M[i][j];
}
for(int i = 0; i < rows; i++) {
char* S;
S = &M[i][0];
if(pal(S) == 1) count++;
}
}
return count;
}
I think your problem is in int pal(char* S) function. You want it to return 1 if a given string of your 2d array is a palindrome to up your count by 1. And anything other than 1 would be non palindrome string.
So i think you should add a return statement after the end of your int pal(char* S) function like this;
int pal(char* S) {
char *p, *start, flag = 1;
p = S;
while(*p != NULL) {
++p;
}
--p;
for(start = S; p >= start && flag;) {
if(*p == *start) {
--p;
start++;
} else
flag = 0;
}
return flag;
}
You could even change your function to bool data type. It's more proper because you only want to return "true" or "false" values.
In this question, we take 2 strings as input say s1 and s2.
Now, first we need to check if s2 is a subsequence of s1. If not, print no.
But if it is, we need to print the minimum number of characters to be deleted from s1 to get s2.
Eg- thistext text
Here, text can be directly found without deleting any characters so the answer is 0.
Eg- cutefriendship crisp
In this case, the answer is 9.
What I've done so far,
#include <bits/stdc++.h>
using namespace std;
int checkIfSub(string s1, string s2, int m, int n)
{
int j = 0;
for(int i = 0; i < m && j < n; i++)
if(s1[i] == s2[j])
j++;
if(j == n)
return 0;
else
return 1;
}
int check(string s1, string s2)
{
int count = 0; string s3;
if(checkIfSub(s1, s2, s1.length(), s2.length()) == 1 || s2.length() > s1.length())
{
cout << "NO\n"; return 0;
}
int j = 0;
for(int i = 0; i < s1.length(); i++)
{
if(s1[i] == s2[j])
{
s3[j] = s1[j];
j++; continue;
}
count++;
}
cout << "YES " << count << "\n";
return 0;
}
int main() {
string s1, s2;
cin >> s1 >> s2;
check(s1, s2);
return 0;
}
My code works well for the second example, but fails the first case.
(This was a question asked in some interview I read online.)
Try something like this:
#include <iostream>
#include <string>
using namespace std;
bool check(const string &s1, const string &s2, int &minToDelete)
{
minToDelete = 0;
bool anySubSeqFound = false;
if (s2.empty())
return false;
string::size_type first = 0;
while ((first = s1.find(s2[0], first)) != string::npos)
{
int numDeleted = 0;
bool isSubSeq = true;
string::size_type next = first + 1;
for(string::size_type j = 1; j < s2.size(); ++j)
{
string::size_type found = s1.find(s2[j], next);
if (found == string::npos)
{
isSubSeq = false;
break;
}
numDeleted += (found - next);
next = found + 1;
}
if (isSubSeq)
{
if (anySubSeqFound)
{
if (numDeleted < minToDelete)
minToDelete = numDeleted;
}
else
{
anySubSeqFound = true;
minToDelete = numDeleted;
}
}
++first;
}
return anySubSeqFound;
}
int main()
{
int minToDelete;
if (check("thistext", "text", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
if (check("cutefriendship", "crisp", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
}
Live Demo
I am having trouble trying to implement a radix sort. This is an assignment, and my professor is less than willing to even point me in the right direction. I have been staring at this code for a long time. Can someone explain to me why my pointers are not working? I did some inspection, and saw that my pointer is not even pointing to the next pointer, and I am very confused as to why. I am not asking for anyone to do my assignment, just some direction.
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define COLUMN 10
using namespace std;
struct List{
int data;
List *p;
};
struct node{
int len = 0;
List *p = NULL;
};
void printList(int list[], int len){
for (int i = 0;i<len;i++){
cout <<list[i] << " ";
}
cout << "\n";
}
void deleteList(node columns[], int len){
for (int j =0; j<COLUMN;j++){
List *curr;
List *prev;
curr = columns[j].p;
for (int i = 0; i<len;i++){
prev = curr;
curr = curr->p;
delete prev;
}
delete curr;
}
}
void overrideArray(node columns[], int a[], int len){
int k = 0; List *curr;
for (int i = 0;i<COLUMN,k<len;i++){
int len = columns[i].len;
cout << len << " length"<< endl;
curr =columns[i].p;
for (int j = 0;j<len;j++){
cout << "plue\n";
if (len == 0) continue;
cout << k <<" plue2\n";
a[k]=curr->data;
cout << "plue3\n";
cout << a[k] << " value";
curr = curr->p;
k++;
}
}
printList(a,len);
}
int main(){
srand(time(NULL));
int length = 10, m,n,i;
node *columns = new node[COLUMN];
List * curr;
int *a = new int [length];
for (int i = 0;i<length;i++){
a[i] = 2;
}
printList(a,length);
m = 10; n = 1; i =0;
while(columns[0].len!=length){
int loc = (a[i]%m)/n;
//cout << loc << endl;
curr = columns[loc].p;
while(curr != NULL){
//cout << "here" << endl;
curr = curr->p;
//cout << curr->data << endl;
}
curr = new List;
cout << curr->p << endl;
curr->data = a[i];
cout << curr->p << endl;
columns[loc].len++;
i++;
if (i == length-1){
overrideArray(columns,a,length);
cout << "here5\n";
deleteList(columns,length);
cout << "here6\n";
i = 0;
m *= 10;
n*=10;
}
}
overrideArray(columns,a,length);
printList(a,length);
return 0;
}
Here is the code I have for a programing assignment I have. Im getting this error when I run the program
"Unhandled exception at at 0x772BC41F in STRUCT2.EXE: Microsoft C++ exception: std::out_of_range at memory location 0x0043ED04." If I understand this right, the error means my array has exceeded the allotted memory space. is that correct? and if this is correct, what am I doing wrong? My input file has less than 30 elements in it.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <sstream>
#include <cctype>
using namespace std;
struct Element
{
string Name;
char eN1;
char eN2;
float Weight;
};
struct Formula
{
char Element1;
char ElementA;
int Atom;
};
void ELEMENTS(Element ElmAry[30]);
float Str2Float(string Weight);
void FORMULAS(Formula FormAry[30]);
float CalculateMoleculeWeight(Element ElmAry[30], Formula FormAry[30]);
int main()
{
ifstream inputFile1;
ifstream inputFile2;
ofstream outputFile;
inputFile1.open("Element.txt");
inputFile2.open("Formula.txt");
outputFile.open("Molecular Weight.txt");
Element ElmAry[30];
Formula FormAry[30];
char inputCh;
int i = 0;
string String1;
string mFor;
string ABRV;
int ElmDigit = 0;
float StringWeight = 0;
string Name;
string Weight;
int LENGTH = 0;
float MOLEWT;
if(!inputFile1)
{
cout << "Couldn't find the Element.txt file." << endl;
return 0;
}
if(!inputFile2)
{
cout << "Couldn't find the Formula.txt file." << endl;
return 0;
}
ELEMENTS(ElmAry);
while(inputFile1)
{
Name = String1.substr(0,2);
ElmAry[i].Name = Name;
Weight = String1.substr(3,10);
String1.clear();
StringWeight = Str2Float(Weight);
ElmAry[i].Weight = StringWeight;
i++;
}
i--;
FORMULAS(FormAry);
while (inputFile2)
{
getline(inputFile2,String1);
LENGTH = String1.length();
int j = 0;
int n = 0;
while( j < LENGTH)
{
int pos = 0;
pos = String1.find(')');
while(n < LENGTH)
{
inputCh = String1.at(n);
if(isalpha(inputCh) && isupper(inputCh))
{
FormAry[j].Element1 = String1.at(n);
n++;
inputCh = String1.at(n);
}
if(isalpha(inputCh) && islower(inputCh))
{
FormAry[j].ElementA = String1.at(n);
n++;
inputCh = String1.at(n);
}
if(ispunct(inputCh))
{
n++;
inputCh = String1.at(n);
ElmDigit = (inputCh-'0');
}
if(isdigit(inputCh))
{
FormAry[j].Atom = ElmDigit;
n++;
}
inputCh = String1.at(n);
j++;
if(iscntrl(inputCh))
{
n++;
inputCh = String1.at(n);
j++;
}
n++;
}
}
}
MOLEWT = CalculateMoleculeWeight(ElmAry, FormAry);
cout << "\t\t MOLECULAR WEIGHT CHART \t\t\n" << endl;
cout << "\n| FORMULA |\t " << "\t| ATOM.WT |" << endl;
cout << "_______________________________";
outputFile << "\t\t MOLECULAR WEIGHT CHART \t\t\n" << endl;
outputFile << "\n| FORMULA |\t " << "\t| ATOM.WT |" << endl;
outputFile << "_______________________________";
for (int a = 0; a < 30; a++)
{
cout << MOLEWT << endl;
outputFile << MOLEWT << endl;
}
inputFile1.close();
inputFile2.close();
outputFile.close();
cin.get();
cin.get();
return 0;
}
void ELEMENTS(Element ElmAry[30])
{
for(int i = 0; i < 30; i++)
{
ElmAry[i].Weight = 0;
}
}
void FORMULAS(Formula FormAry[30])
{
for(int x = 0; x < 30; x++)
{
for(int x = 0; x < 9; x++)
{
FormAry[x].Atom = 1;
}
}
}
float Str2Float (string x)
{
stringstream ss(x);
float StringWeight;
ss >> StringWeight;
return StringWeight;
}
float CalculateMoleculeWeight(Element ElmAry[30], Formula FormAry[30])
{
int i;
int j=0;
float MoleWT = 0;
float MoleSum = 0;
char e1;
char e2;
char f1;
char f2;
for(i = 0; i < 30; i++)
{
f1 = FormAry[j].Element1;
f2 = FormAry[j].ElementA;
e1 = ElmAry[i].eN1;
e2 = ElmAry[i].eN1;
if
(e1 == f1 && e2 == f2)
{
MoleWT = ElmAry[i].Weight * FormAry[j].Atom;
MoleSum = MoleSum + MoleWT;
j++;
}
}
return MoleSum;
}
when I get to
while(inputFile1)
{
Name = String1.substr(0,2);
ElmAry[i].Name = Name;
Weight = String1.substr(3,10);//invalid string position
String1.clear();
StringWeight = Str2Float(Weight);
ElmAry[i].Weight = StringWeight;
i++;
}
i--;
Weight = String1.substr(3,10); gives me an invalid string position
std::out_of_range is an exception you get when you attempt to access memory outside the space you've allocated (in an STL container). In this particular case, you are accessing areas of a std::string that has not been allocated:
Weight = String1.substr(3,10); // empty string or string.length() < 4 throws here
std::string::substr takes index parameters that must be within the bounds of the array encapsulated by std::string. If the string is only 2 characters long, and you attempt to get characters starting at the 4th position, you will see the std::out_of_range exception. You should check the length prior to doing this kind of operation.
Additionally, you are declaring your arrays:
Element ElmAry[30];
Formula FormAry[30];
But you are looping through an entire file (which potentially has more than 30 elements). Thus, when i >= 30, you are out of bounds (and behavior will be undefined).
You can fix that by using std::vector, which will allow the array to be dynamically sized, or another collection (e.g. std::list, std::deque).