What's the correct approach to solve SPOJ www.spoj.com/problems/PRHYME/? - c++

I have been trying to solve this problem SPOJ www.spoj.com/problems/PRHYME/? for several days, but have had no success.
Here is the problem in brief:
Given is a wordlist L, and a word w. Your task is to find a word in L that forms a perfect rhyme with w. This word u is uniquely determined by these properties:
It is in L.
It is different from w.
Their common suffix is as long as possible.
Out of all words that satisfy the previous points, u is the lexicographically smallest one.
Length of a word will be<=30.
And number of words both in the dictionary and the queries can be 2,50,000.
I am using a trie to store all the words in the dictionary reversed.
Then to solve the queries I proceed in the following fashion:-
If word is present in the trie,delete it from trie.
Now traverse the trie from the root till the point the character from the query string match the trie values.Let this point where last character match was found be P.
Now from this point P onward ,I traverse the trie using DFS,and on encountering a leaf node,push the string formed to the possible results list.
Now I return the lexicographic ally smallest result from this list.
When I submit my solution on SPOJ,my solution gets a Time Limit Exceeded Error.
Can someone please suggest a detailed algorithm or hint to solve this problem ?
I can post my code if required.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<vector>
#include<string>
#include<algorithm>
#include<cctype>
#include<cstdlib>
#include<utility>
#include<map>
#include<queue>
#include<set>
#define ll long long signed int
#define ull unsigned long long int
const int alpha=26;
using namespace std;
struct node
{
int value;
node * child[alpha];
};
node * newnode()
{
node * newt=new node;
newt->value=0;
for(int i=0;i<alpha;i++)
{
newt->child[i]=NULL;
}
return newt;
}
struct trie
{
node * root;
int count;
trie()
{
count=0;
root=newnode();
}
};
trie * dict=new trie;
string reverse(string s)
{
int l=s.length();
string rev=s;
for(int i=0;i<l;i++)
{
int j=l-1-i;
rev[j]=s[i];
}
return rev;
}
void insert(string s)
{
int l=s.length();
node * ptr=dict->root;
dict->count++;
for(int i=0;i<l;i++)
{
int index=s[i]-'a';
if(ptr->child[index]==NULL)
{
ptr->child[index]=newnode();
}
ptr=ptr->child[index];
}
ptr->value=dict->count;
}
void dfs1(node *ptr,string p)
{
if(ptr==NULL) return;
if(ptr->value) cout<<"word" <<p<<endl;
for(int i=0;i<26;i++)
{
if(ptr->child[i]!=NULL)
dfs1(ptr->child[i],p+char('a'+i));
}
}
vector<string> results;
pair<node *,string> search(string s)
{
int l=s.length();
node * ptr=dict->root;
node *save=ptr;
string match="";
int i=0;
bool no_match=false;
while(i<l and !no_match)
{
int in=s[i]-'a';
if(ptr->child[in]==NULL)
{
save=ptr;
no_match=true;
}
else
{
ptr=ptr->child[in];
save=ptr;
match+=in+'a';
}
i++;
}
//cout<<s<<" matched till here"<<match <<" "<<endl;
return make_pair(save,match);
}
bool find(string s)
{
int l=s.length();
node * ptr=dict->root;
string match="";
for(int i=0;i<l;i++)
{
int in=s[i]-'a';
//cout<<match<<"match"<<endl;
if(ptr->child[in]==NULL)
{
return false;
}
ptr=ptr->child[in];
match+=char(in+'a');
}
//cout<<match<<"match"<<endl;
return true;
}
bool leafNode(node *pNode)
{
return (pNode->value != 0);
}
bool isItFreeNode(node *pNode)
{
int i;
for(i = 0; i < alpha; i++)
{
if( pNode->child[i] )
return false;
}
return true;
}
bool deleteHelper(node *pNode, string key, int level, int len)
{
if( pNode )
{
// Base case
if( level == len )
{
if( pNode->value )
{
// Unmark leaf node
pNode->value = 0;
// If empty, node to be deleted
if( isItFreeNode(pNode) )
{
return true;
}
return false;
}
}
else // Recursive case
{
int index = (key[level])-'a';
if( deleteHelper(pNode->child[index], key, level+1, len) )
{
// last node marked, delete it
free(pNode->child[index]);
pNode->child[index]=NULL;
// recursively climb up, and delete eligible nodes
return ( !leafNode(pNode) && isItFreeNode(pNode) );
}
}
}
return false;
}
void deleteKey(string key)
{
int len = key.length();
if( len > 0 )
{
deleteHelper(dict->root, key, 0, len);
}
}
string result="***";
void dfs(node *ptr,string p)
{
if(ptr==NULL) return;
if(ptr->value )
{
if((result)=="***")
{
result=reverse(p);
}
else
{
result=min(result,reverse(p));
}
}
for(int i=0;i<26;i++)
{
if(ptr->child[i]!=NULL)
dfs(ptr->child[i],p+char('a'+i));
}
}
int main(int argc ,char ** argv)
{
#ifndef ONLINE_JUDGE
freopen("prhyme.in","r",stdin);
#endif
string s;
while(getline(cin,s,'\n'))
{
if(s[0]<'a' and s[0]>'z')
break;
int l=s.length();
if(l==0) break;
string rev;//=new char[l+1];
rev=reverse(s);
insert(rev);
//cout<<"...........traverse..........."<<endl;
//dfs(dict->root);
//cout<<"..............traverse end.............."<<endl;
}
while(getline(cin,s))
{
results.clear();
//cout<<s<<endl;
int l=s.length();
if(!l) break;
string rev;//=new char[l+1];
rev=reverse(s);
//cout<<rev<<endl;
bool del=false;
if(find(rev))
{
del=true;
//cout<<"here found"<<endl;
deleteKey(rev);
}
if(find(rev))
{
del=true;
//cout<<"here found"<<endl;
deleteKey(rev);
}
else
{
//cout<<"not here found"<<endl;
}
// cout<<"...........traverse..........."<<endl;
//dfs1(dict->root,"");
// cout<<"..............traverse end.............."<<endl;
pair<node *,string> pp=search(rev);
result="***";
dfs(pp.first,pp.second);
//cout<<"search results"<<endl;
//dfs1(pp.first,pp.second);
//cout<<"end of search results"<<
for(int i=0;i<results.size();i++)
{
results[i]=reverse(results[i]);
// cout<<s<<" "<<results[i]<<endl;
}
string smin=result;
if(del)
{
insert(rev);
}
cout<<smin<<endl;
}
return 0;
}

Your algorithm (using a trie that stores all reversed words) is a good start. But one issue with it is that for each lookup, you have to enumerate all words with a certain suffix in order to find the lexicographically smallest one. For some cases, this can be a lot of work.
One way to fix this: In each node (corresponding to each suffix), store the two lexicographically smallest words that have that suffix. This is easy to maintain while building the trie by updating all ancestor nodes of each newly added leaf (see pseudo-code below).
Then to perform a lookup of a word w, start at the node corresponding to the word, and go up in the tree until you reach a node which contains a descendant word other than w. Then return the lexicographically smallest word stored in that node, or the second smallest in case the smallest is equal to w.
To create the trie, the following pseudo-code can be used:
for each word:
add word to trie
let n be the node corresponding to the new word.
for each ancestor a of n (including n):
if a.smallest==null or word < a.smallest:
a.second_smallest = a.smallest
a.smallest = word
else if a.second_smallest==null or word < a.second_smallest:
a.second_smallest = word
To lookup a word w:
let n be the node corresponding to longest possible suffix of w.
while ((n.smallest==w || n.smallest==null) &&
(n.second_smallest==w || n.second_smallest==null)):
n = n.parent
if n.smallest==w:
return n.second_smallest
else:
return n.smallest
Another similar possibility is to use a hash table mapping all suffixes to the two lexicographically smallest words instead of using a trie. This is probably easier to implement if you can use std::unordered_map.

Related

Permutations of String Using Stack C++

The program I have below finds all the permutations of a given string using a stack without recursion. I am having some trouble understanding what the place in the struct is for and how it plays into the logic for the algorithm. Could anyone help me understand this code? I have a struct that only has two entities:
class Node
{
public:
string word; // stores the word in the node
Node *next;
};
I would just like to understand why the place entity is needed.
Here is the code that finds all the permutations of a given string:
struct State
{
State (std::string topermute_, int place_, int nextchar_, State* next_ = 0)
: topermute (topermute_)
, place (place_)
, nextchar (nextchar_)
, next (next_)
{
}
std::string topermute;
int place;
int nextchar;
State* next;
};
std::string swtch (std::string topermute, int x, int y)
{
std::string newstring = topermute;
newstring[x] = newstring[y];
newstring[y] = topermute[x]; //avoids temp variable
return newstring;
}
void permute (std::string topermute, int place = 0)
{
// Linked list stack.
State* top = new State (topermute, place, place);
while (top != 0)
{
State* pop = top;
top = pop->next;
if (pop->place == pop->topermute.length () - 1)
{
std::cout << pop->topermute << std::endl;
}
for (int i = pop->place; i < pop->topermute.length (); ++i)
{
top = new State (swtch (pop->topermute, pop->place, i), pop->place + 1, i, top);
}
delete pop;
}
}
int main (int argc, char* argv[])
{
if (argc!=2)
{
std::cout<<"Proper input is 'permute string'";
return 1;
}
else
{
permute (argv[1]);
}
return 0;
}
Place helps you to know where is going to be the next character "swap". As you can see, it increments inside the for loop. As you can see, inside that for loop, it behaves like a pivot and i increments in order to behave like a permutator (by swapping characters)

print all words of a dictionary using trie

I am working on a dictionary using a trie with the following struct in c
struct trie_node {
int is_end; //0 is is not the end of the word ,otherwise 1
char c;
struct trie_node* child[26];
};
I am able to insert words, search words and I would like to print all the words of the dictionary. Not sure how to handle it. I was trying to print
void print(struct trie_node node) {
int i = 0;
for (i = 0; i < 26; i++) {
if (node->child[i] != NULL) {
printf("%c", node->child[i]->c);
print(node->child[i]);
}
}
}
But it is not printing correctly
if for example I have the words
beer
bee
bear
beast
it is printing
bearster
it should print
bearbeastbeebeer
How can I print correctly the list of words ?
You need to keep track of the path (path from the root to the current node). When you reach to an end node (is_end is true), you print the path which is the dictionary word.
One approach is to use an array of char and keep track of its length so you know how many of elements you need to print. See the code below:
void print_path (char *path, int len){
int i;
for(i = 0; i < len; i++)
printf("%c", path[i]);
}
void print(struct trie_node* node, char *path, int len) {
// sanity check
if (! node)
return;
// current node is part of the current path, so add it
path[len++] = node->c;
// if it is an end node then print the path
if (node->is_end)
print_path(path, len);
// now go through the children and recursive call
int i = 0;
for (i = 0; i < 26; i++) {
if (node->child[i] != NULL) {
print(node->child[i], path, len);
}
}
}
int main(){
// proper allocation for the trie
// ...
// calling the print, assuming the height of tree is at most 128
char path[128];
print(b, path, 0);
}
you can try to use node.child[i]->c,when use struct var you must use a ".",when use struct point must use "->" or "(&point).",i don't know my think is true : )

why this C++ Trie implementation is showing odd behaviour?

I implemented this class to create a trie data structure. The function
unsigned long Insert(string) //inserts the string in trie & return no of words in trie
void PrintAllWords(); // prints all words in trie separated by space in dictionary order
implementation works correctly and prints all the words inserted from a text file of english dictionary words when the number of words is not very large, but when supplied with a file with some 350k words it only prints out a b c d upto z.
private variables
struct TrieTree
{
std::map<char,struct TrieTree*> map_child;
std::map<char,unsigned long> map_count; //keeps incrementing count of char in map during insertion.
bool _isLeaf=false; // this flag is set true at node where word ends
};
struct TrieTree* _root=NULL;
unsigned long _wordCount=0;
unsigned long _INITIALIZE=1;
Below is complete implementation with driver program. The program is executable.
#include<iostream>
#include<map>
#include<fstream>
class Trie
{
private:
struct TrieTree
{
std::map<char,struct TrieTree*> map_child;
std::map<char,unsigned long> map_count;
bool _isLeaf=false;
};
struct TrieTree* _root=NULL;
unsigned long _wordCount=0;
unsigned long _INITIALIZE=1;
struct TrieTree* getNode()
{
return new TrieTree;
};
void printWords(struct TrieTree* Tptr,std::string pre)
{
if(Tptr->_isLeaf==true)
{
std::cout<<pre<<" ";
return;
}
std::map<char,struct TrieTree*>::iterator it;
it=Tptr->map_child.begin();
while(it!=Tptr->map_child.end())
{
pre.push_back(it->first);
printWords(it->second,pre);
pre.erase(pre.length()-1); //erase last prefix character
it++;
}
}
public:
Trie()
{
_root=getNode();
}
unsigned long WordCount()
{
return _wordCount;
}
unsigned long WordCount(std::string pre) //count words with prefix pre
{
if(WordCount()!=0)
{
struct TrieTree *Tptr=_root;
std::map<char,unsigned long>::iterator it;
char lastChar;
for(int i=0;i<pre.length()-1;i++)
{
Tptr=Tptr->map_child[pre[i]];
}
lastChar=pre[pre.length()-1];
it=Tptr->map_count.find(lastChar);
if(it!=Tptr->map_count.end())
{
return Tptr->map_count[lastChar];
}
else
{
return 0;
}
}
return 0;
}
unsigned long Insert(std::string key) //return word count after insertion
{
struct TrieTree *Tptr =_root;
std::map<char,struct TrieTree*>::iterator it;
if(!SearchWord(key))
{
for(int level=0;level<key.length();level++)
{
it=Tptr->map_child.find(key[level]);
if(it==Tptr->map_child.end())
{
//alphabet does not exist in map
Tptr->map_child[key[level]]=getNode(); // new node with value pointing to it
Tptr->map_count[key[level]] = _INITIALIZE;
Tptr=Tptr->map_child[key[level]]; //assign pointer to newly obtained node
if(level==key.length()-1)
Tptr->_isLeaf=true;
}
else
{ //alphabet exists at this level
Tptr->map_count[key[level]]++;
Tptr=Tptr->map_child[key[level]];
}
}
_wordCount++;
}
return _wordCount;
}
bool SearchWord(std::string key)
{
struct TrieTree *Tptr =_root;
std::map<char,struct TrieTree*>::iterator it;
for(int level=0;level<key.length();level++)
{
it=Tptr->map_child.find(key[level]);
// cout<<" "<<Tptr->map_child.size()<<endl; //test to count entries at each map level
if(it!=Tptr->map_child.end())
{
Tptr=Tptr->map_child[key[level]];
}
else
{
return false;
}
}
if(Tptr->_isLeaf==true)
return true;
return false;
}
void PrintAllWords()
{ //print all words in trie in dictionary order
struct TrieTree *Tptr =_root;
if(Tptr->map_child.empty())
{
std::cout<<"Trie is Empty"<<std::endl;
return;
}
printWords(Tptr,"");
}
void PrintAllWords(std::string pre)
{ //print all words in trie with prefix pre in Dictionary order
struct TrieTree *Tptr =_root;
if(Tptr->map_child.empty())
{
std::cout<<"Trie is Empty"<<std::endl;
return;
}
for(int i=0;i<pre.length();i++)
{
Tptr=Tptr->map_child[pre[i]];
}
printWords(Tptr,pre);
}
};
int main(){
Trie t;
std::string str;
std::fstream fs;
fs.open("words.txt",std::ios::in);
while(fs>>str){
t.Insert(str);
}
t.PrintAllWords();
return 0;
}
I don't understand the output, please take a look at the code and suggest a fix. Thanks
When you add the word "a", if there is no word starting with 'a' in the tree, you will add a "leaf" node with 'a' as the value. If you then add a word starting with 'a', such as "an", you will add the 'n' node as a child of the 'a' node. However, when you print all the words, you stop recursing when you hit a leaf node, meaning you ignore all the other words starting with that word.
Simple solution: remove the return from printWords.
Similarly if you already have "an" in the tree, when you add 'a', you don't mark it as a leaf, so it will never be output.
Simple solution: Set _isLeaf when adding a word, even if the node already exists (i.e. add Tptr->_isLeaf=true; to the else clause in Insert
I think you would be better off changing _isLeaf to something like _isWord as it seems odd to have leaf nodes with child items.

Searching a string inside a char array using Divide and Conquer

Let's say that I have a struct array and each element has a name. Like:
struct something{
char name[200];
}a[NMAX];
Given a new string (char array), i need to find the correct index for it using divide and conquer. Like:
char choice[200];
cin>>chioce;
int k=myFunction(choice); // will return the index, 0 otherwise
// of course, could be more parameters
if( k )
cout<<k;
I don't know how to create that searching function (I tried, I know how D&C works but i'm still learning! ).
And no, i don't want to use strings !
This is what i tried:
int myFunction(char *choice, int l,int r) // starting with l==0 && r==n-1
{
int m;
if(strcmp(a[m].name,choice)==0)
return m;
else{
m=(l+r)/2;
return myFunction(choice,l,m-1);
return myFunction(choice,m+1,r);
}
}
This is my solution for your above problem. But i have modified a few things in your code.
#include<iostream>
using namespace std;
#define NMAX 10
struct something{
char *name; //replaced with char pointer so that i can save values the way i have done
}a[NMAX];
int myFunction(char *choice, int l,int r) // starting with l==0 && r==NMAX-1
{
if(l>r) //return if l has become greater than r
return -1;
int m=(l+r)/2;
if(strcmp(a[m].name,choice)==0)
return m+1;
else if(l==r) //returned -1 as the value has not matched and further recursion is of no use
return -1;
else{
int left= myFunction(choice,l,m-1);//replaced return
int right= myFunction(choice,m+1,r);//by saving values returned
if(left!=-1) //so that i can check them,
return left; //otherwise returning from here onlywould never allow second satatement to execute
if(right!=-1)
return right;
else
return -1;
}
}
int main(){
a[0].name="abc";
a[1].name="a";
a[2].name="abcd";
a[3].name="abcf";
a[4].name="abcg";
a[5].name="abch";
a[6].name="abcj";
a[7].name="abck";
a[8].name="abcl";
a[9].name="abcr";
char choice[200];
cin>>choice;
int k=myFunction(choice,0,NMAX-1); // will return the index, 0 otherwise
// of course, could be more parameters
if( k !=-1)
cout<<k;
else
cout<<"Not found";
return 0;
}
Hope it will help.

Palindrome Partitioning (how to figure out how to use DFS)

My general question is how to figure out how to use DFS. It seems to be a weak part of my knowledge. I have vague idea but often get stuck when the problem changes. It caused a lot of confusion for me.
For this question, I got stuck with how to write DFS with recursion.
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
[
["aa","b"],
["a","a","b"]
]
My first attempt was stuck in the loop of the helper function. Then from searching on internet, I found that bool palindrome(string s) can be written as a different signature.
bool palindrome(string &s, int start, int end)
This leads to the correct solution.
Here's the code of my initial attempt:
class Solution {
public:
bool palindrome(string s)
{
int len = s.size();
for (int i=0;i<len/2; i++)
{
if (s[i]!=s[len-i])
return false;
}
return true;
}
void helper( int i, string s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (i==slen-1&&flag)
{
ret.push_back(p);
}
for (int k=i; k<slen; k++)
{
if (palindrome(s.substr(0,k)))
{
p.push_back(s.substr(0,k)); //Got stuck
}
}
i++;
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
Correct one:
class Solution {
public:
bool palindrome(string &s, int start, int end)
{
while(start<end)
{
if (s[start]!=s[end])
return false;
start++;
end--;
}
return true;
}
void helper( int start, string &s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (start==slen)
{
ret.push_back(p);
return;
}
for (int i=start; i<s.size(); i++)
{
if (palindrome(s, start, i))
{
p.push_back(s.substr(start,i-start+1));
helper(i+1,s,p,ret);
p.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
Edit Dec. 4, 2014: I saw some approach using dynamical programming but can't understand the code completely.
esp. isPalin[i][j] = (s[i] == s[j]) && ((j - i < 2) || isPalin[i+1][j-1]);
Why j-I<2 instead of j-I<1?
class Solution {
public:
vector<vector<string>> partition(string s) {
int len = s.size();
vector<vector<string>> subPalins[len+1];
subPalins[0] = vector<vector<string>>();
subPalins[0].push_back(vector<string>());
bool isPalin[len][len];
for (int i=len-1; i>=0; i--)
{
for (int j=i; j<len; j++)
{
isPalin[i][j] = (s[i]==s[j])&&((j-i<2)||isPalin[i+1][j-1]);
}
}
for (int i=1; i<=len;i++)
{
subPalins[i]=vector<vector<string>>();
for (int j=0; j<i; j++)
{
string rightStr=s.substr(j,i-j);
if (isPalin[j][i-1])
{
vector<vector<string>> prepar=subPalins[j];
for (int t=0; t<prepar.size(); t++)
{
prepar[t].push_back(rightStr);
subPalins[i].push_back(prepar[t]);
}
}
}
}
return subPalins[len];
}
};
What exactly are you asking? You have correct working code and your non-working code which is not that different.
I guess I can point out several issues with your code - may be it will be helpful to you:
in the palindrome() function you should compare s[i] to s[len-1-i] rather than to just s[len-i] in the if, since in former case you will compare 1st element (having index 0) to the non-existent element (index len). That might be the reason helper() got stuck.
in the helper() function flag is not initialized. In the for cycle, the end condition should be k<slen-1 instead of k<slen, since in latter case you will omit checking the substring that includes the terminal symbol of the string. Also, incrementing i in the end of helper() is pointless. Finally, indentations are messy in the helper() function.
Not sure why you use DFS - what is the meaning of your graph, what are the vertices and edges here? As to how the recursion works here: in the helper() function you start checking substrings of increased length for being palindrome. If the palindrome is found, you place it into p vector (which represent your current partitioning) and try to break the remainder of the string into palindromes by calling helper() recursively. If you succeed in that (i.e. if the whole string is completely partitioned into palindromes) you place the contents of p vector (current partitioning) into ret (set of all found partitionings), and then clear p to prepare it for the analysis of the next partition (purge of p is achieved by pop_back() call that follows recursive call of helper()). If, on the other hand, you fail to completely break string into palindromes, the p is purged as well, but without transferring its content into ret (this is due to the fact that recursive call for the last piece of string - which is not a palindrome - returns without calling helper() for the final symbol and thus pushing p into ret does not occur). Therefore you end up having all possible palindrome partitionings in the ret.
Hi~ this is my code using DFS + backtracking.
class Solution
{
public:
bool isPalindrome (string s) {
int i = 0, j = s.length() - 1;
while(i <= j && s[i] == s[j]) {
i++;
j--;
}
return (j < i);
}
void my_partition(string s, vector<vector<string> > &final_result, vector<string> &every_result ) {
if (s.length() ==0)
final_result.push_back(every_result);
for (int i =1; i <= s.length();++i) {
string left = s.substr(0,i);
string right = s.substr(i);
if (isPalindrome(left)) {
every_result.push_back(left);
my_partition(right, final_result, every_result);
every_result.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string> > final_result;
vector<string> every_result;
my_partition(s, final_result, every_result);
return final_result;
}
};
I have done Palindrome Partitioning using backtracking. Depth-first search was used here, idea is to split the given string so that the prefix is a palindrome. push prefix in a vector now explore the string leaving that prefix and then finally pop the last inserted element,
Well on spending time on backtracking is of the form, choose the element, explore without it and unchoose it.
enter code here
#include<iostream>
#include<vector>
#include<string>
using namespace std;
bool ispalidrome(string x ,int start ,int end){
while(end>=start){
if(x[end]!=x[start]){
return false;
}
start++;
end--;
}
return true;
}
void sub_palidrome(string A,int size,int start,vector<string>&small, vector < vector < string > >&big ){
if(start==size){
big.push_back(small);
return;
}
for(int i=start;i<size;i++){
if( ispalidrome(A,start,i) ){
small.push_back(A.substr(start,i-start+1));
sub_palidrome(A,size,i+1,small,big);
small.pop_back();
}
}
}
vector<vector<string> > partition(string A) {
int size=A.length();
int start=0;
vector <string>small;
vector < vector < string > >big;
sub_palidrome(A,size,start,small,big);
return big;
}
int main(){
vector<vector<string> > sol= partition("aab");
for(int i=0;i<sol.size();i++){
for(int j=0;j<sol[i].size();j++){
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
}