ACM 1113 - Multiple Morse Matches - c++

I'm trying to solve the ACM 1113 (http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3554) and I think I got a valid solution (at least the output seems to be ok for multiple entries that I've tried), the only problem is my solution is being rejected by the submission system and I don't know why since it doesn't take that long to run on my machine, could anyone please help me?
/*
* Multiple morse matches
*/
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
std::map<char,string> decodeToMorse;
string toMorse(string w){
string morse = "";
for(int i = 0; i < w.size(); i++){
morse = morse + decodeToMorse[w[i]];
}
return morse;
}
int findPossibleTr( string morse, vector<string> dictMorse, vector<string> dictWords, int index){
int count = 0;
for(int i = 0; i < dictMorse.size(); i++){
if(morse.compare( index, dictMorse[i].size(), dictMorse[i]) == 0){
//cout<<"Found " << dictWords[i] << " on index "<<index<<endl;
if(index+dictMorse[i].size()>=morse.size()){
//cout<<"Adding one for "<< dictWords[i]<<endl;
count+=1;
//return 1;
}else{
count += findPossibleTr(morse, dictMorse, dictWords, index+dictMorse[i].size());
}
}
}
return count;
}
int main(){
int ncases;
cin>>ncases;
decodeToMorse['A'] = ".-";
decodeToMorse['B'] = "-...";
decodeToMorse['C'] = "-.-.";
decodeToMorse['D'] = "-..";
decodeToMorse['E'] = ".";
decodeToMorse['F'] = "..-.";
decodeToMorse['G'] = "--.";
decodeToMorse['H'] = "....";
decodeToMorse['I'] = "..";
decodeToMorse['J'] = ".---";
decodeToMorse['K'] = "-.-";
decodeToMorse['L'] = ".-..";
decodeToMorse['M'] = "--";
decodeToMorse['N'] = "-.";
decodeToMorse['O'] = "---";
decodeToMorse['P'] = ".--.";
decodeToMorse['Q'] = "--.-";
decodeToMorse['R'] = ".-.";
decodeToMorse['S'] = "...";
decodeToMorse['T'] = "-";
decodeToMorse['U'] = "..-";
decodeToMorse['V'] = "...-";
decodeToMorse['W'] = ".--";
decodeToMorse['X'] = "-..-";
decodeToMorse['Y'] = "-.--";
decodeToMorse['Z'] = "--..";
for(int i = 0; i < ncases; i++){
vector<string> dictMorse;
vector<string> dictWords;
string morse;
cin >> morse;
int ndict;
cin >> ndict;
for(int j = 0; j < ndict; j++){
string dictw;
cin >> dictw;
dictMorse.push_back(toMorse(dictw));
dictWords.push_back(dictw);
}
cout<<findPossibleTr(morse,dictMorse, dictWords,0)<<endl;
if(ncases != 1 && i != ncases-1)
cout<<endl;
}
}
I've tried the following input:
3
.---.-.---...
7
AT
ATC
COS
OS
A
T
C
.---.--.-.-.-.---...-.---.
6
AT
TACK
TICK
ATTACK
DAWN
DUSK
.........
5
E
EE
EEE
EEEE
EEEEE
And I get the following output (as expected):
5
2
236
Only problem is that when I submit it to the judge system it says the algorithm spends more than its maximum time limit (3s). Any ideas?

Your algorithm runs out of time because it performs an exhaustive search for all distinct phrases within the dictionary that match the given Morse code. It tries every single possible concatenation of the words in the dictionary.
While this does give the correct answer, it takes time exponential in both the length of the given Morse string and the number of words in the dictionary. The question does actually mention that the number of distinct phrases is at most 2 billion.
Here's a simple test case that demonstrates this behavior:
1
... // 1000 dots
2
E
EE
The correct answer would be over 1 billion in this case, and an exhaustive search would have to enumerate all of them.
A way to solve this problem would be to use memoization, a dynamic programming technique. The key observation here is that a given suffix of the Morse string will always match the same number of distinct phrases.
Side note: in your original code, you passed morse, dictMorse and dictWords by value to your backtracking function. This results in the string and the two vectors being copied at every invocation of the recursive function, which is unnecessary. You can pass by reference, or (since this is in a competitive programming context where the guidelines of good code architecture can be bent) just declare them in global scope. I opted for the former here:
int findPossibleTr( const string &morse, const vector<string> &dictMorse, const vector<string> &dictWords, vector<int> &memo, int index ) {
if (memo[index] != -1) return memo[index];
int count = 0;
/* ... */
return memo[index] = count;
}
And in your initialization:
/* ... */
vector<int> memo(morse.size(), -1); // -1 here is a signal that the values are yet unknown
cout << findPossibleTr(morse, dictMorse, dictWords, memo, 0) << endl;
/* ... */
This spits out the answer 1318412525 to the above test case almost instantly.
For each of the T test cases, findPossibleTr is computed only once for each of the M suffixes of the Morse string. Each computation considers each of the N words once, with the comparison taking time linear in the length K of the word. In general, this takes O(TMNK) time which, depending on the input, might take too long. However, since matches seem to be relatively sparse in Morse code, it should run in time.
A more sophisticated approach would be to make use of a data structure such as a trie to speed up the string matching process, taking O(TMN) time in total.
Another note: it is not actually necessary for decodeToMorse to be a map. It can simply be an array or a vector of 26 strings. The string corresponding to character c is then decodeToMorse[c - 'A'].

I'm writing up my process for this situation, hope it helps.
I would first analyse the algorithm to see if it's fast enough for the problem. For example if the input of n can be as large as 10^6 and the time limit being 1 sec, then an O(n2) algorithm is not going to make it.
Then, would test against an input as 'heavy' as possible for the problem statement (max number of test cases with max input length or whatever). If it exceeds the time limit, there might be something in the code that can be optimized to get a lower constant factor. It's possible that after all the hard optimizations it's still not fast enough. In that case I would go back to step #1
After making sure the algorithm is ok, I would try to generate random inputs and try a few rounds to see if there're any peculiar cases the algorithm is yet to cover.

There are three things I'd suggest doing to improve the performance of this code.
Firstly, all the arguments to toMorse and findPossibleTr are being passed by value. This will make a copy, which for objects like std::string and std::vector will be doing memory allocations. This will be quite costly, especially for the recursive calls to findPossibleTr. To fix it, change the function declarations to take const references, like so:
string toMorse(const string& w)
int findPossibleTr( const string& morse, const vector<string>& dictMorse, const vector<string>& dictWords, int index)
Secondly, string concatenation in toMorse is doing allocations making and throwing away lots of strings. Using a std::stringstream will speed that up:
#include <sstream>
string toMorse(const string& w){
stringstream morse;
for(int i = 0; i < w.size(); i++){
morse << decodeToMorse[w[i]];
}
return morse.str();
}
Finally, we can reuse the vectors inside the loop in main, instead of destructing the old ones and creating new ones each iteration by using clear().
// ...
vector<string> dictMorse;
vector<string> dictWords;
for(size_t i = 0; i < ncases; i++){
dictMorse.clear();
dictWords.clear();
string morse;
cin >> morse;
// ...
Putting it all together on my machine gives me a 30% speed up, from 0.006s to 0.004s on your test case. Not too bad. As a bonus, if you are on an Intel platform, Intel's optimization manual says that unsigned integers are faster than signed integers, so I've switched all ints to size_ts, which also fixes up some warnings. The complete code now becomes
/*
* Multiple morse matches
* Filipe C
*/
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <map>
using namespace std;
std::map<char,string> decodeToMorse;
string toMorse(const string& w){
stringstream morse;
for(size_t i = 0; i < w.size(); i++){
morse << decodeToMorse[w[i]];
}
return morse.str();
}
size_t findPossibleTr( const string& morse, const vector<string>& dictMorse, const vector<string>& dictWords, size_t index){
size_t count = 0;
for(size_t i = 0; i < dictMorse.size(); i++){
if(morse.compare( index, dictMorse[i].size(), dictMorse[i]) == 0){
//cout<<"Found " << dictWords[i] << " on index "<<index<<endl;
if(index+dictMorse[i].size()>=morse.size()){
//cout<<"Adding one for "<< dictWords[i]<<endl;
count+=1;
//return 1;
}else{
count += findPossibleTr(morse, dictMorse, dictWords, index+dictMorse[i].size());
}
}
}
return count;
}
int main(){
size_t ncases;
cin>>ncases;
decodeToMorse['A'] = ".-";
decodeToMorse['B'] = "-...";
decodeToMorse['C'] = "-.-.";
decodeToMorse['D'] = "-..";
decodeToMorse['E'] = ".";
decodeToMorse['F'] = "..-.";
decodeToMorse['G'] = "--.";
decodeToMorse['H'] = "....";
decodeToMorse['I'] = "..";
decodeToMorse['J'] = ".---";
decodeToMorse['K'] = "-.-";
decodeToMorse['L'] = ".-..";
decodeToMorse['M'] = "--";
decodeToMorse['N'] = "-.";
decodeToMorse['O'] = "---";
decodeToMorse['P'] = ".--.";
decodeToMorse['Q'] = "--.-";
decodeToMorse['R'] = ".-.";
decodeToMorse['S'] = "...";
decodeToMorse['T'] = "-";
decodeToMorse['U'] = "..-";
decodeToMorse['V'] = "...-";
decodeToMorse['W'] = ".--";
decodeToMorse['X'] = "-..-";
decodeToMorse['Y'] = "-.--";
decodeToMorse['Z'] = "--..";
vector<string> dictMorse;
vector<string> dictWords;
for(size_t i = 0; i < ncases; i++){
dictMorse.clear();
dictWords.clear();
string morse;
cin >> morse;
size_t ndict;
cin >> ndict;
for(size_t j = 0; j < ndict; j++){
string dictw;
cin >> dictw;
dictMorse.push_back(toMorse(dictw));
dictWords.push_back(dictw);
}
cout<<findPossibleTr(morse,dictMorse, dictWords,0)<<endl;
if(ncases != 1 && i != ncases-1)
cout<<endl;
}
}

Related

Finding if a string is contained in another string without "find" in c++

I wrote this program to find if a string is contained in another string (see paragraph below this, I tried to explain what I want it to do). When I test it, sometimes it works, most of the times it gives me the error "String subscript out of range". I'm very new to C++, I'd appreciate someone to tell me how can I improve this code or why I'm being dumb, because I really don't get why it doesn't work.
what i want this to do is find if string one can be found in string way;
so i want it to check for every letter of string way if the letter [i] is equal to the first letter of the string one (way[i+0]==one[0]),
and way[i+1]==one[1] and so on for all letters in one.
so for example way = abankjve and one = ank
it takes the first letter in way (a) and gets the first letter in one(a). the're equal. but we see that way[0+1] is not equal to one[1]. so o can't be true.
it goes on like this till it gets to way[2]=a. way[2+0]=one[0]. o is true. then it checks way[2+1]=one[1]. true! then it checks way[2+2]=one[2]. true! then
one is contained in way.
#include <iostream>
using namespace std;
int main()
{
string way, one;
bool o=false;
cin >> way;
cin >> one;
for (int i = 0; i < way.size(); i++)
{
for (int k = 0; k < one.size(); k++)
{
if (way[i + k]==one[k])
{
o = true;
}
}
}
cout << o << endl;
}
If you think about it, way[i+k] will result in index out of range.
say way is length of 5 and one is length of 3.
i+k's range is 0 <= i + k <= 6. Witch is bigger than the possible index of way.
change first for loop for (int i = 0; i < way.size(); i++) to
for (int i = 0; i <= (int)way.size() - one.size(); i++)
Note I've used static_cast to int. *.size() returns unsigned int so if one's size is bigger than way's size, the result won't be what you've imagined.
#include <iostream>
#include <string>
int main()
{
std::string way, one;
std::cin >> way;
std::cin >> one;
bool found{};
for (size_t i = 0; i < way.size() - one.size()+1; i++)
{
if(one == way.substr(i, one.size())) {
found = true;
break;
}
}
std::cout << found;
}
Demo

C++ 'std::bad_alloc' what(): std::bad_alloc

I am trying to run the below C++ code and I get this error :
Could anyone please help me clarify why is this the issue
Input : input/text_4.txt 9
terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc
Aborted (core dumped)
After reading a few similar threads, the solution is to check dynamic memory allocation. However, my code does not have any dynamically allocated memory
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
vector<string> arrangefile(vector<string>& scale, int width, int &number) {
int beginning = 0; int total = 0;
vector<string> result;
for(int i = 0; i < scale.size(); i++)
{
total += scale[i].size(); // add length of each word
if(total + i - beginning > width) // checking if the value has exceeded the maximum width
{
total -= scale[i].size();
string sentence= "",low="";
int last = i-1;
int space = width - total; // calculate number of spaces in each line
int check = max(last-beginning, 1);
int even = space/check;
while(even--){
low += " ";
}
int mod = space%check;
for(int j = beginning; j <= last; j++)
{
sentence += scale[j]; //find all values in a sentence
if(j < last || beginning == last)
sentence += low; // add the word low to the larger sentence
if(j - beginning < mod)
sentence += " ";
}
result.push_back(sentence); // add the sentence to the vector
number++; // counts the number of sentences
beginning = i;
total = scale[i].size();
}
}
string sentence =""; // for the last line
int last = scale.size()-1;
int check = last-beginning;
int space = width - total - check;
string low="";
while(space--){
low += " ";
}
for(int j = beginning; j <= last; j++)
{
sentence += scale[j];
if(j < last){
sentence += " ";
}
}
sentence += low;
result.push_back(sentence); // // add the sentence to the vector
number++; // counts the number of sentences
return result;
}
int main(){
string filepath, word;
int M, number=0;
cin >> filepath;
cin >> M;
ifstream fin;
fin.open(filepath.c_str());
unsigned found = filepath.find_last_of("/");
string b = filepath.substr(found+1);
int create = b.size();
string between = b.substr(0, create-4);
string final = between + "_formatted.txt";
string ending = "output/" + final;
mkdir ("output", 0777);
ofstream fout;
fout.open(ending);
for(int i = 0, count = 0; i<M; i++, count ++){
if(count == 9){
fout<<count;
count = -1;
}
else
fout<<count;
}
fout<<endl;
vector <string> first;
vector <string> second;
while(fin >> word){
first.push_back(word);
}
if(first.empty()){
cout<<"0 formatted lines written to "<< ending<<endl;
}
else{
second = arrangefile(first, M,number);
for (auto i = second.begin(); i != second.end(); ++i)
fout << *i <<endl;
cout<<number<<" formatted lines written to "<<ending<<endl;
}
fin.close();
fout.close();
return 0;
}
input file text_4.txt:
This is because not very many happy things happened
in the lives of the three Baudelaire youngsters.
Input: input/text_4.txt 8
When I run your code, on the i==16 iteration of the outer loop in arrangefile, we get width==8 and total==10, with check==1. As a result, even is initialized to -2, and so the while(even--) loop is (nearly) infinite. So it attempts to add spaces to low until it runs out of memory.
(Note that the memory used by std::string is dynamically allocated, so your code does have dynamic memory allocation. The same for std::vector.)
I haven't analyzed your algorithm closely enough to figure out the correct fix, but it's possible your loop should be while(even-- > 0) instead.
I'll second the tip in the comments to use your debugger, and I'll repost the link: What is a debugger and how can it help me diagnose problems?. That's how I found this bug.
I ran the program under the debugger gdb. It ran for a few seconds, at which point I got suspicious because the program doesn't appear do anything complicated enough to take that much computation time. So I interrupted the program (Ctrl-C) which let me see where it was and what it was doing. I could see that it was within the while(even--) loop. That was also suspicious because that loop should complete very fast. So I inspected the value of even (with the command p even) and saw that it was a large negative number. That could only happen if it had started as a negative number, which logically could only happen if total were greater than width. Inspecting their values I could see that this was indeed the case.
Maybe this will be helpful as you learn more about using your debugger.

looking for a faster way to help reduce/create a huge list of strings

I tried to write an algorithm to guess correctly in the game "Masterminds",
it works the average number of guesses is 6, but it takes a lot of time to calculate the best guess.
I used the idea of Knuth the algorithm works as follows:
Create the set S of 1296 possible codes (1111, 1112 ... 6665, 6666).
Start with initial guess 1122 (Knuth gives examples showing that other first guesses such as 1123, 1234 do not win in five tries on
every code).
Play the guess to get a response of colored and white pegs.
If the response is four colored pegs, the game is won, the algorithm terminates.
Otherwise, remove from S any code that would not give the same response if the current guess were the code.
In my code step 2 is to take random number.
I used vector<string> for this.
AllPoss is the vector full of strings, I guess is the last guess that was used. answer is the count of bulls and cows looks like "x,y" (where x and y are numbers)
void bullpgia::SmartGuesser::remove(string guess, string answer)
{
for (auto i= AllPoss.begin();i != AllPoss.end();i++){
string token = *i;
if (calculateBullAndPgia(token, guess) != answer)
AllPoss.erase(i--);
}
}
this is the part it take a lot of time to calculate is there any way of improvement?
to creating the list i used :
void bullpgia::SmartGuesser::All() {
/**
* creates a pool of all the possibilities strings
* we then delete the ones we dont need
* #param length is the length of the word we need to guess
*/
for(int i=0;i<pow(10,length);i++){
stringstream ss;
ss << setw(length) << setfill('0') << i;
string s = ss.str();
AllPoss.push_back(s);
}
}
the function calculateBullAndPgia(string , string) is:
string calculateBullAndPgia(const string &choice, const string &guess) {
string temp = choice;
string temp2 = guess;
unsigned int bull = 0;
unsigned int pgia = 0;
for (int i = 0; i < temp.length(); i++) {
if (temp[i] == temp2[i]) {
bull++;
temp[i] = 'a';
temp2[i] = 'z';
}
}
for (int i = 0; i < temp.length(); i++) {
for (int j = 0; j < temp2.length(); j++) {
if (i != j && temp[i] == temp2[j]) {
pgia++;
temp[i] = 'a';
temp2[j] = 'z';
}
}
}
return to_string(bull) + "," + to_string(pgia);
}
Erasing a single element in the middle of a vector is O(n). My guess is that you wind up doing it O(n) times per call to SmartGuesser::remove. Then you loop over that so you probably have a O(n^3) algorithm. You instead could use std::remove_if, which is O(n), to move all the to-be-erased elements to the end of the vector where they can be cheaply erased.:
AllPoss.erase(std::remove_if(AllPos.begin(), AllPos.end(), [&](const std::string& token, const std::string& guess) { return calculateBullAndPgia(token, guess) != answer; }), AllPos.end());

Logical error from std string find method and count algorithm

When I was about to solve a project euler problem in C++, this was some of the experimentation code I made. It produced a quite unexpected result, so I solved it in an other programming language. But I really want to understand why this error occured. The part one of the code executes as expected, it does not print AAAA. But in part two, the logically equivalent code (the if statement) executes when the variable s is AAAA. And I have no idea why. I hope I made my problem clear, every answer given is highly appreciated! Thanks :)
Note: i'm using count from <algorithm>
#include <iostream>
#include <algorithm>
using namespace std;
int main (int argc, char** argv) {
string alt = "LOA";
// CODE PART 1
string stringToFind = "AAA";
string df = "AAAA";
if (df.find(stringToFind) == string::npos && count(df.begin(), df.end(), 'L') <= 1) {
cout << df; // this does not print AAAA
}
/* CODE PART 2:
this was an attempt to print out every four length string combination
of the characters L, O, A where strings with three A's in a row and
more than one L were excluded.
*/
for (size_t i = 0; i < 3; i++) {
char c1 = alt[i];
for (size_t iT = 0; iT < 3; iT++) {
char c2 = alt[iT];
for (size_t itr = 0; itr < 3; itr++) {
char c3 = alt[itr];
for (size_t itrI = 0; itrI < 3; itrI++) {
char c4 = alt[itrI];
string s = string(&c1)+string(&c2)+string(&c3)+string(&c4);
if (s.find(stringToFind) == string::npos && count(s.begin(), s.end(), 'L') <= 1) {
cout << s << endl; // this however, does print out AAAA
}
}
}
}
}
return 0;
}
You have written
string s = string(&c1)+string(&c2)+string(&c3)+string(&c4);
You meant:
string s = string(1,c1)+string(1,c2)+string(1,c3)+string(1,c4);
or
string s = string(&c1,1)+string(&c2,1)+string(&c3,1)+string(&c4,1);
In your code, you have invoked the string constructor which takes a pointer to a nul-terminated array of char, but you given it a pointer to a single char. That's going to invoke all sorts of undefined behaviour.
Either invoke the constructor that takes a a counter + a single char or, the one which takes a pointer and a count, and you can tell it there is exactly one character at that address.
Edit There is no constructor which takes a single char. You have to give it a count + char. Which means it's not so pretty.

Need help optimizing a program that finds all possible substrings

I have to find all possible, unique substrings from a bunch of user-input strings. This group of substrings has to be alphabetically sorted without any duplicate elements, and the group must be queryable by number. Here's some example input and output:
Input:
3 // This is the user's desired number of strings
abc // So the user inputs 3 strings
abd
def
2 // This is the user's desired number of queries
7 // So the user inputs 2 queries
2
Output:
// From the alphabetically sorted group of unique substrings,
bd // This is the 7th substring
ab // And this is the 2nd substring
Here's my implementation:
#include <map>
#include <iostream>
using namespace std;
int main() {
int number_of_strings;
int number_of_queries;
int counter;
string current_string;
string current_substr;
map<string, string> substrings;
map<int, string> numbered_substrings;
int i;
int j;
int k;
// input step
cin >> number_of_strings;
string strings[number_of_strings];
for (i = 0; i < number_of_strings; ++i)
cin >> strings[i];
cin >> number_of_queries;
int queries[number_of_queries];
for (i = 0; i < number_of_queries; ++i)
cin >> queries[i];
// for each string in 'strings', I want to insert every possible
// substring from that string into my 'substrings' map.
for (i = 0; i < number_of_strings; ++i) {
current_string = strings[i];
for (j = 1; j <= current_string.length(); ++j) {
for (k = 0; k <= current_string.length()-j; ++k) {
current_substr = current_string.substr(k, j);
substrings[current_substr] = current_substr;
}
}
}
// my 'substrings' container is now sorted alphabetically and does
// not contain duplicate elements, because the container is a map.
// but I want to make the map queryable by number, so I'm iterating
// through 'substrings' and assigning each value to an int key.
counter = 1;
for (map<string,string>::iterator it = substrings.begin();
it != substrings.end(); ++it) {
numbered_substrings[counter] = it->second;
++counter;
}
// output step
for (i = 0; i < number_of_queries; ++i) {
if (queries[i] > 0 && queries[i] <= numbered_substrings.size()) {
cout << numbered_substrings[queries[i]] << endl;
} else {
cout << "INVALID" << endl;
}
}
return 0;
}
I need to optimize my algorithm, but I'm not sure how to do it. Maybe it's the fact that I have a second for loop for assigning new int keys to each substring. Help?
Check out Suffix tree. It usually runs in O(n) time:
This article was helpful for me:
http://allisons.org/ll/AlgDS/Tree/Suffix/
Minor notes:
1. include <string>
2. careful with those } else {; one day you'll have a lot of else if branches
and a lot of lines and you'll wonder where an if starts and where it ends
3. careful with unsigned versus signed mismatching... again, one day it will
come back and bite (also, it's nice to compile without errors or warnings)
4. don't try to define static arrays with a variable size
5. nice with ++ i. not many know it has a slight performance boost
(maybe not noticeable with today's processors but still)
While I do agree that using proper algorithms when needed (say bubble sort, heap sort etc. for sorting, binary search, binary trees etc. for searching), sometimes I find it nice to do an optimization on current code. Imagine having a big project and implementing something requires rewrites... not many are willing to wait for you (not to mention the required unit testing, fat testing and maybe fit testing). At least my opinion. [and yes, I know some are gonna say that if it is so complicated then it was written badly from the start - but hey, you can't argue with programmers that left before you joined the team :P]
But I do agree, using existing stuff is a good alternative when called for. But back to the point. I tested it with
3, abc, def, ghi
4, 1, 3, 7, 12
I can't say whether yours is any slower than mine or vice-versa; perhaps a random string generator that adds maybe 500 inputs (then calculates all subs) might be a better test, but I am too lazy at 2 in the morning. At most, my way of writing it might help you (at least to me it seems simpler and uses less loops and assignments). Not a fan of vectors, cos of the slight overhead, but I used it to keep up with your requirement of dynamic querying... a static array of a const would be faster, obviously.
Also, while not my style of naming conventions, I decided to use your names so you can follow the code easier.
Anyway, take a look and tell me what you think:
#include <map>
#include <iostream>
#include <string> // you forgot to add this... trust me, it's important :)
#include <vector> // not a fan, but it's not that bad IF you want dynamic buffers
#include <strstream>
using namespace std;
int main ()
{
unsigned int number_of_strings = 0;
// string strings[number_of_strings]; // don't do this... you can't assign static arrays of a variable size
// this just defaults to 0; you're telling the compiler
cin >> number_of_strings;
map <string, string> substrings;
string current_string, current_substr;
unsigned int i, j, k;
for (i = 0; i < number_of_strings; ++ i)
{
cin >> current_string;
substrings[current_string] = current_string;
for (j = 1; j <= current_string.length(); ++ j)
{
for (k = 0; k <= current_string.length() - j; ++ k)
{
current_substr = current_string.substr(k, j);
substrings[current_substr] = current_substr;
}
}
}
vector <string> numbered_substrings;
for (map <string, string>::iterator it = substrings.begin(); it != substrings.end(); ++ it)
numbered_substrings.push_back(it->second);
unsigned int number_of_queries = 0;
unsigned int query = 0;
cin >> number_of_queries;
current_string.clear();
for (i = 0; i < number_of_queries; ++ i)
{
cin >> query;
-- query;
if ((query >= 0) && (query < numbered_substrings.size()))
current_string = current_string + numbered_substrings[query] + '\n';
else
cout << "INVALID: " << query << '\n' << endl;
}
cout << current_string;
return 0;
}