I was solving the following question from Facebook Hacker Cup:
Since you crave state-of-the-art technology, you've just purchased a phone with a great new feature: autocomplete! Your phone's version of autocomplete has some pros and cons. On the one hand, it's very cautious. It only autocompletes a word when it knows exactly what you're trying to write. On the other hand, you have to teach it every word you want to use.
You have N distinct words that you'd like to send in a text message in order. Before sending each word, you add it to your phone's dictionary. Then, you write the smallest non-empty prefix of the word necessary for your phone to autocomplete the word. This prefix must either be the whole word, or a prefix which is not a prefix of any other word yet in the dictionary.
What's the minimum number of letters you must type to send all N words?
I am implementing a trie for this as follows:
struct trie {
int ct;
vector<trie*> child;
trie() {
ct = 0;
for(int i = 0; i < 26; i++) {
child.push_back(nullptr);
}
}
~trie() {
//cerr << "called\n";
for(int i = 0; i < 26; i++) {
delete child[i];
}
child.clear();
}
};
void add(trie* t, const string &str, int i) {
//ct++;
int index = str[i] - 'a';
if(t->child[index] == nullptr) {
t->child[index] = new trie();
}
t->child[index]->ct++;
i++;
if(i != str.length()) {
add(t->child[index], str, i);
}
}
int getL(trie* t, const string &str, int i) {
if(i == str.length()) {
return i;
}
int index = str[i] - 'a';
if(t->child[index]->ct == 1) {
return i + 1;
}
else {
return getL(t->child[index], str, i + 1);
}
}
int solve() {
int n;
cin >> n;
string s;
//cin >> s;
int i;
trie* root = new trie();
int ans = 0;
for(i = 0; i < n; i++) {
cin >> s;
cerr << "READ " << s << '\n';
add(root, s, 0);
cerr << "DONE ADD\n";
ans += getL(root, s, 0);
}
//int ans = 0;
delete (root);
return ans;
}
However I seem to be getting Segmentation fault(Core Dumped) error which I understand means that I am accessing an invalid memory location however I cannot seem to figure out where it is the case in my code. Any help would be appreciated.
Related
I'm a C++ beginner, and I was wondering how I can rewrite this code without using void functions, and use it all in main().
I know that this program needs to get the longest consecutive substring in a string,
but is there another way to do it without using functions?
substring in C++
#include <iostream>
using namespace std;
void longestConsecutivecharacter(string letters){
int finalResult = 1;
int letterCounter = 1;
char flcrcs;
for (int i = 1; i < letters.size(); i++) {
if (letters[i] == letters[i + 1]) {
++letterCounter;
}
else {
if(letterCounter>finalResult)
flcrcs=letters[i-1];
finalResult = max(finalResult, letterCounter);
letterCounter = 1;
}
}
finalResult = max(finalResult, letterCounter);
for(int i=0;i<finalResult;i++)
cout<<flcrcs;
};
int main(){
string letters;
cout << "Enter a string: ";
cin>>letters;
cout << "The first longest consecutive repeating character substring is: ";
longestConsecutivecharacter(letters);
return 0;
}
Why do you want to do it without functions? This method is better and more portable.
If you still want to, you can just take the code and put it in main, like this:
int main(){
string letters;
cout << "Enter a string: ";
cin>>letters;
int finalResult = 1;
int letterCounter = 1;
char flcrcs;
for (int i = 1; i < letters.size(); i++) {
if (letters[i] == letters[i + 1]) {
++letterCounter;
}
else {
if(letterCounter>finalResult) {
flcrcs=letters[i-1];
finalResult = max(finalResult, letterCounter);
letterCounter = 1;
}
}
finalResult = max(finalResult, letterCounter);
for(int i=0;i<finalResult;i++)
cout << "The first longest consecutive repeating character substring is: ";
cout<<flcrcs;
};
I am writing a backtracking algorithm, I think my writing is correct, but the output is wrong. I went to debug and found that the execution:When the program executes to this sentence in the for loop, sometimes it directly skips the following statement in the for loop.
Question is here:
Permutation Sequence
I have written a debugging environment, which can be run directly.
My answer is here:
class Solution {
public:
int index = 0, N, K;
string ans;
string getPermutation(int n, int k) {
N = n;
K = k;
string str;
backtrace(str, 0);
return ans;
}
void backtrace(string &str, int start) {
if (start == N) {
index++;
if (index == K) {
ans = str;
}
return;
}
for (int i = start; i < N; i++) {
if (index == K) {
return;
}
string temp = str; //For loop to this sentence will not execute the following statement
str += to_string(i + 1);
backtrace(str, i + 1);
str = temp;
}
}
};
int nn(int n) {
if (n == 1) {
return 1;
}
return nn(n - 1) * n;
}
int main() {
Solution so;
for (int i = 1; i <= nn(3); i++) {
cout << so.getPermutation(3, i) << endl;
}
system("pause");
}
I’m not sure if it’s the c++ problem or mine, or it might be my algorithm,but I’ve checked it many times.
My previous thinking was wrong,#Igor Tandetnik remended me . This problem requires a bit of mathematical skills or it will time out. Thanks for your help #john and #Igor Tandetnik.
My finally code is here:
class Solution {
private:
vector<int> hash;
vector<int> factorial;
bool flag = true;
void dfs(int cur, int n, int &k, string &ret, int &cnt, string path){
if(cur == n){
ret = path;
flag = false;
return;
}
int temp = factorial[n-cur-1];
for(int i=0; i<n; i++){
if(hash[i] && flag){
if(temp < k ){
k = k - temp;
continue;
}
path.push_back(i+1+'0');
hash[i] = 0;
dfs(cur+1,n,k,ret,cnt,path);
hash[i] = 1;
path.pop_back();
}
}
}
public:
string getPermutation(int n, int k) {
//calculate the factorial
if(n == 1) return "1";
factorial.resize(n);
factorial[0] = 1;
factorial[1] = 1;
if(n > 2){
for(int i=2; i<n; i++){
factorial[i] = i * factorial[i-1];
}
}
string ret;
string path;
hash.resize(n,1);
int cnt = 0;
dfs(0,n,k,ret,cnt,path);
return ret;
}
};
Assuming n = 4, k = 17, we can know that the 17th permutation is [3,4,1,2]. In order to find it, we need to do pruning at key nodes. How to judge? As shown in the figure, when we start the search, we visit the purple node "1", and notice that if we continue to visit (deep search) at this time, it is actually meaningless, because there are at most 3 from this node! =6 full permutations and combinations, and what we are looking for is the 17th, 6<17, so we prun directly; visit the purple node "2", the same thing can be seen, you need pruning at this node; visit the purple node "3" ", now that the conditions are met, 6> 5, you need to search down. (Note here that a simple counting technique is that when a node needs to be pruned, we need to update the value of k, k = k-the node corresponds to the factorial number).
Author: edward_wang
I am writing code for Leetcode problem 38. Count and Say. It doesn't pass the cases, so I add some cout to debug. Please tell me is there a normal way to debug nested for loop, where should I add the cout expression. I don't want to know how to modify the code to pass the cases.
Here is my code:
class Solution {
public:
string countAndSay(int n) {
string cur("1");
while (--n) {
string tmp = cur;
string next;
for (int i = 0; i < tmp.size();) {
cout << "i:" << i << endl;
int count = 1;
for (int j = i + 1; j < tmp.size(); j++) {
if (tmp[j] != tmp[0]) {
break;
}
count++;
}
cout << "count:" << count << endl;
next += std::to_string(count) + tmp[0];
cout << "cur:" << cur << endl;
i += count;
}
cur = next;
cout << n << cur << endl;
}
return cur;
}
};
You're gonna have to use a debugger for that, and step by step go through your algorithm to find the bugs. It's hard to debug someone else's algorithm.
This'll pass through:
#include <string>
struct Solution {
static const std::string countAndSay(int n) {
if (not n) {
return "";
}
std::string res = "1";
while (--n) {
std::string curr = "";
for (int index = 0; index < res.size(); index++) {
int count = 1;
while ((index + 1 < res.size()) and (res[index] == res[index + 1])) {
count++;
index++;
}
curr += std::to_string(count) + res[index];
}
res = curr;
}
return res;
}
};
Java Solutions
class Solution {
public String countAndSay(int n) {
if (n == 1)
return "1";
String prev = countAndSay(n - 1);
StringBuilder str = new StringBuilder();
int i = 0;
while (i < prev.length()) {
char curr = prev.charAt(i);
int j = 0;
while (i + j < prev.length() && prev.charAt(i + j) == curr)
j++;
str.append(j);
str.append(curr);
i += j;
}
return str.toString();
}
}
Here is one of LeetCode's solutions using regex:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
public String countAndSay(int n) {
String currSeq = "1";
// Pattern to match the repetitive digits
String regexPattern = "(.)\\1*";
Pattern pattern = Pattern.compile(regexPattern);
for (int i = 1; i < n; ++i) {
Matcher m = pattern.matcher(currSeq);
StringBuffer nextSeq = new StringBuffer();
// each group contains identical and adjacent digits
while (m.find()) {
nextSeq.append(m.group().length() + String.valueOf(m.group().charAt(0)));
}
// prepare for the next iteration
currSeq = nextSeq.toString();
}
return currSeq;
}
}
and here's another LeetCode's solution also using Sliding Window:
class Solution {
public String countAndSay(int n) {
LinkedList<Integer> prevSeq = new LinkedList<Integer>();
prevSeq.add(1);
// Using -1 as the delimiter
prevSeq.add(-1);
List<Integer> finalSeq = this.nextSequence(n, prevSeq);
StringBuffer seqStr = new StringBuffer();
for (Integer digit : finalSeq) {
seqStr.append(String.valueOf(digit));
}
return seqStr.toString();
}
protected LinkedList<Integer> nextSequence(int n, LinkedList<Integer> prevSeq) {
if (n <= 1) {
// remove the delimiter before return
prevSeq.pollLast();
return prevSeq;
}
LinkedList<Integer> nextSeq = new LinkedList<Integer>();
Integer prevDigit = null;
Integer digitCnt = 0;
for (Integer digit : prevSeq) {
if (prevDigit == null) {
prevDigit = digit;
digitCnt += 1;
} else if (digit == prevDigit) {
// in the middle of the sub-sequence
digitCnt += 1;
} else {
// end of a sub-sequence
nextSeq.add(digitCnt);
nextSeq.add(prevDigit);
// reset for the next sub-sequence
prevDigit = digit;
digitCnt = 1;
}
}
// add the delimiter for the next recursion
nextSeq.add(-1);
return this.nextSequence(n - 1, nextSeq);
}
}
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
I am trying to implement the algorithm RLE with simple input like:
ddddddddddhhhhhhhhhhhhhhhttttttttttttt
code:
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
int main() {
vector<char> read;
ifstream file;
file.open("file.txt");
if (!file) {
cout << "Unable to open";
}
char v;
while(file>>v) {
read.push_back(v);
}
char x;
int count=0;
for(int i=0; i<read.size(); i++) {
x = read[i];
if(x != read[++i]) {
cout << x << "1";
}
while(x == read[++i]) {
count++;
}
cout << x << count;
count = 0;
}
return 0;
}
The output I am getting is:
d9d1h12h1t10t1
Please help me with the code.
Update: I have updated the question as I have realized few things.
Plus: This code produced no output, is there anything wrong which I am doing wrong?
char o;
char n;
int count=0;
for(int i=0; i<read.size(); i++) {
o = read[i];
n = read[++i];
while(o == n) {
count++;
}
cout << o << count;
if(o != n) {
cout << o << "1";
} count = 0;
}
return 0;
This loop:
char x;
int count=0;
for(int i=0; i<read.size(); i++) {
int j=i;
x = read[i];
if(x != read[++j]) {
cout << x << "1";
}
while(x == read[++j]) {
count++;
}
cout << x << count;
}
Has several errors. First, you should use two indices, i and j. i is going through each element of read, but then j is iterating through a subsequence too. What you want is to go through each element only once, and in each case either print or increase the count. However having a for loop and moving the index inside too is not a very good practice, is rather error-prone. Also you have to cout statements that are do not run at the right time (you don't wan to print something on every iteration, only when the character changes). You could do it with a while loop, or using a simpler structure like:
// If there are no characters finish
if (read.empty()) {
return 0;
}
// Get the first character
char lastChar = read[0];
int count = 1; // We have counted one character for now
// Go through each character (note start from 1 instead of 0)
for(int i = 1; i < read.size(); i++) {
// Get the next char
char newChar = read[i];
// If it is different, print the current count and reset the counter
if (lastChar != newChar) {
cout << lastChar << count;
count = 1;
lastChar = newChar;
} else { // Else increase the counter
count++;
}
}
// Print the last one
cout << lastChar << count;
return 0;
I have a task that is difficult for me to handle. The task is: Create recursive function that can be generate a string of length N (N <= 100), formed by the letters 'A', 'B' and 'C' and does not containing two identical adjacent substring. For example: enter for N = 6 and the program should generate such a string in which no one else to repeated substrings: ABACAB. Wrong strings are: AABACA - because 'A' is to 'A'; ABCBCA - as 'BC' is to 'BC' and ABCABC is also wrong because 'ABC' is to 'ABC'.
I made a version of the program but an iterative way, here is the code:
#include <iostream>
#include <ctime>
using namespace std;
const char letters[] = "ABC";
char generate_rand()
{
return letters[rand() % 3];
}
int check(char *s, int pos)
{
for (int i = 1; i <= (pos + 1)/2; i++)
{
int flag = 1;
for (int j = 0; j < i; j++)
if (s[pos-j] != s[pos-i-j])
{
flag = 0;
break;
}
if (flag)
return 1;
}
return 0;
}
int main()
{
char s[100];
int n;
cout << "enter n: ";
cin >> n;
srand(time(NULL));
for (int i = 0; i < n; i++)
{
do
{
s[i] = generate_rand();
} while (check(s, i));
cout << s[i] << " ";
}
cout << " ok" << endl;
system("pause");
return 0;
}
I think the entrance of the recursive function may need to be the number of characters in the string, which will seek to repeat with an adjacent string and each time increased by 1, but not more than half the length of the original string, but do not know how to do it.
So lets start with a simple recursive function which prints 10 letters but doesn't check anything:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (strlen(buf) < max_length)
addLetter(buf);
}
int main()
{
srand(time(NULL)); //I forgot srand!
int max_length = 10; //ask user to input max_length, like you had earlier
char buf[100];
memset(buf,0,sizeof(buf));
addLetter(buf, max_length);
printf("\n%s\n", buf);
return 0;
}
Now lets change the recursive function, get it to check just 1 letter:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (len > 0)
{
if (buf[len] == buf[len-1])
buf[len] = 0;
}
if (strlen(buf) < max_length)
addLetter(buf);
}
Next step, check 2 letters with previous ones etc. You should be able to take it from here.