In pratica costruisco un albero con tutte le parole, identifico il ramo dove c’è la parola più lunga, visito tutti i rami tranne quello e poi visito quel ramo lasciando la parola più lunga per ultima. Qualcuno può dirmi dove sbaglio?
Premetto che il tuo codice non l’ho letto (mi fido sul fatto che hai implementato correttamente l’albero).
Premetto anche che i TRIE li ho letti l’altro giorno per puro caso e non so implementarli.
Ma facendomi un disegnino su carta forse ho capito dove sbagli.
Come hai capito, devi “stampare” per ultima la parola più lunga.
Ma questo ragionamento lo applichi anche per le precedenti N-1 parole?
Non ne sono sicuro eh, (nemmeno io l’ho risolto/provato quel problema) ma ad intuito, tra due o più sotto-alberi, devi scegliere prima quello che possiede meno nodi.
Per le parole prima l’ordine di stampa corrisponde all’ordine di inserimento nell’albero, quindi non è detto che vengano stampate prima le parole più corte… ma ciò è necessario? Prima o poi tutte le parole devono essere cancellate (interamente o in parte), quindi l’ordine non è indifferente?
Per le parole prima l'ordine di stampa corrisponde all'ordine di inserimento nell'albero, quindi non è detto che vengano stampate prima le parole più corte... ma ciò è necessario? Prima o poi tutte le parole devono essere cancellate (interamente o in parte), quindi l'ordine non è indifferente?
marcoBeretta
L'importante è lasciare per ultima quella più lunga
Per le parole prima l'ordine di stampa corrisponde all'ordine di inserimento nell'albero, quindi non è detto che vengano stampate prima le parole più corte... ma ciò è necessario? Prima o poi tutte le parole devono essere cancellate (interamente o in parte), quindi l'ordine non è indifferente?
marcoBeretta
L'importante è lasciare per ultima quella più lunga
Qui c’è il mio codice. Io applico tutte le idee che avete detto, quindi trie che stampa l’ultima parola alla fine e stampa anche parole che non finiscono nelle foglie ma faccio 40/100. Idee?
Qui c'è il mio codice. Io applico tutte le idee che avete detto, quindi trie che stampa l'ultima parola alla fine e stampa anche parole che non finiscono nelle foglie ma faccio 40/100. Idee?
http://pastebin.com/vmHXpm4g
EmanueleRossi
Come implementazione è un po' contorta. In realtà è sufficiente salvarsi l'indice della parola più lunga ed inserirla nel trie alla fine in un modo un po' diverso. Io l'ho fatto mettendo ogni sottoalbero che comprendeva quella parola sempre più a destra, quindi come ultima scelta per ogni nodo. Poi il resto è un normale trie.
Qui c'è il mio codice. Io applico tutte le idee che avete detto, quindi trie che stampa l'ultima parola alla fine e stampa anche parole che non finiscono nelle foglie ma faccio 40/100. Idee?
http://pastebin.com/vmHXpm4g
EmanueleRossi
Come implementazione è un po' contorta. In realtà è sufficiente salvarsi l'indice della parola più lunga ed inserirla nel trie alla fine in un modo un po' diverso. Io l'ho fatto mettendo ogni sottoalbero che comprendeva quella parola sempre più a destra, quindi come ultima scelta per ogni nodo. Poi il resto è un normale trie.
Io mi salvo in ogni nodo la lunghezza della parola più lunga che inizia da lì, poi faccio nth_element sui figli in modo da tenere il sottoalbero con la parola più lunga per ultimo
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int contaOp = 0;
struct trie
{
bool print;
char c;
vector<trie> sons;
int mWord;
};
bool operator<(const trie &a, const trie&b)
{
return a.mWord < b.mWord;
}
void addWord(string w, trie &node)
{
if(w.empty())
{
node.print = true;
return;
}
bool found = false;
int i = 0;
for(i = 0; i < (int)node.sons.size() && !found; i++)
if(node.sons[i].c == w[0]) found = true;
if(!found)
{
trie newNode;
newNode.c = w[0];
newNode.mWord = 0;
newNode.print = false;
node.sons.push_back(newNode);
}
else i--;
node.sons[i].mWord = max(node.sons[i].mWord, (int)w.length());
addWord(w.substr(1, string::npos), node.sons[i]);
}
void printSol(int &N, trie &nodo, ofstream &out)
{
if(nodo.print)
{
N--;
out << "P\n";
contaOp++;
}
if(nodo.sons.empty())
return;
nth_element(nodo.sons.begin(), nodo.sons.end()-1, nodo.sons.end());
int i = 0;
while(i < nodo.sons.size())
{
out << nodo.sons[i].c << "\n";
contaOp++;
printSol(N, nodo.sons[i], out);
if(N > 0) { out << "-\n"; contaOp++; }
i++;
}
}
int main()
{
ifstream in("input.txt");
ofstream out("output.txt");
int N;
string w;
trie triet;
triet.c = '0';
triet.print = false;
in >> N;
for(int i = 0; i < N; i++)
{
in >> w;
addWord(w, triet);
}
out << " \n";
printSol(N, triet, out);
out.seekp(ios_base::beg);
out << contaOp;
return 0;
}
C’è comunque una soluzione alternativa più lenta ma che porta comunque ai 100/100. Basta farsi un vector di string e ordinarlo con una funzione compare “modificata” in modo che resti per ultima la parola più lunga
Lo so che il mio codice è molto contorto, però io faccio proprio cosi, costruisco il trie, poi coloro nel trie la parola piu lunga, e dopo la stampo per ultima…però bho…proverò a reimplementare…