This problem can be solved by a BFS on a graph that modeling the doublet relationships. If the pair
AAnd
BForms a doublet, then there is a edge
AAnd
BIn the graph.
You can divide the dictionary into portions by word size, then handle each portion separately. To get a better RT, build each graph lazily only when needed.
Code:
- /*************************************** **********************************
- * Copyright (c) 2008 by liukaipeng *
- * Liukaipeng at gmail dot com *
- **************************************** *********************************/
- /* @ Judge_id 00000 10150 C ++ "doublets "*/
- # Include <cstring>
- # Include <iostream>
- # Include <fstream>
- # Include <string>
- # Include <map>
- # Include <queue>
- # Include <list>
- # Include <vector>
- # Include <map>
- Using namespace STD;
- Int const wordcount = 25200;
- Int const wordsize = 20;
- Typedef vector <char *> wordtable;
- Struct strcomp
- {Bool operator () (char * S1, char * S2) {return strcmp (S1, S2) <0 ;}};
- Typedef Map <char *, Int, strcomp> wordmap;
- Typedef vector <int> wordgraph;
- Bool adjacent (char const * S1, char const * S2)
- {
- Bool adj = false;
- For (INT I = 0; S1 [I]! = '/0'; ++ I ){
- If (S1 [I]! = S2 [I]) {
- Adj =! Adj;
- If (! Adj) break;
- }
- }
- Return adj;
- }
- Void build_wordgraph (wordtable const & wt, wordgraph & WG)
- {
- WG. Resize (wt. Size ());
- For (INT I = 0; I <wt. Size ()-1; ++ I ){
- For (Int J = I + 1; j <wt. Size (); ++ J ){
- If (adjacent (wt [I], wt [J]) {
- WG [I]. push_back (j );
- WG [J]. push_back (I );
- }
- }
- }
- }
- Bool get_doublets (wordgraph const & WG, int S, int T, list <int> & doublets)
- {
- Queue <int> q;
- Vector <bool> visited (WG. Size (), false );
- Vector <int> previous (WG. Size ());
- Q. Push (s );
- Visited [s] = true;
- Bool found = false;
- While (! Q. Empty ()){
- Int v = Q. Front ();
- Q. Pop ();
- If (V = T ){
- Found = true;
- Break;
- }
- For (INT I = 0, size = WG [v]. Size (); I <size; ++ I ){
- Int A = WG [v] [I];
- If (! Visited [a]) {
- Q. Push ();
- Visited [a] = true;
- Previous [a] = V;
- }
- }
- }
- If (found ){
- For (; t! = S; t = previous [T]) doublets. push_front (t );
- Doublets. push_front (t );
- }
- Return found;
- }
- Int main (INT argc, char * argv [])
- {
- # Ifndef online_judge
- Filebuf In, out;
- Cin. rdbuf (in. Open (string (argv [0]) + ". In"). c_str (), ios_base: In ));
- Cout. rdbuf (out. Open (string (argv [0]) + ". Out"). c_str (), ios_base: Out ));
- # Endif
- Char words [wordcount] [wordsize];
- Int nwords = 0;
- For (; cin. Getline (words [nwords], wordsize) & words [nwords] [0]! = '/0 ';
- ++ Nwords ){}
- /* Index words by size */
- Vector <wordtable> WTS (wordsize );
- Vector <wordmap> WMS (wordsize );
- For (INT I = 0; I <nwords; ++ I ){
- Int size = strlen (words [I]);
- WTS [size]. push_back (words [I]);
- WMS [size]. insert (make_pair (words [I], WTS [size]. Size ()-1 ));
- }
- /* We will build wordgraph lazily */
- Vector <wordgraph> WGS (wordsize );
- Char source [wordsize], target [wordsize];
- Int ncases = 0;
- While (CIN> source> Target ){
- If (ncases ++! = 0) cout <'/N ';
- List <int> doublets;
- Bool found = false;
- Int size = strlen (source );
- Wordtable & Wt = WTS [size];
- Wordmap & WM = WMS [size];
- Wordgraph & WG = WGS [size];
- If (size = strlen (target )){
- If (WG. Empty () build_wordgraph (wt, WG );
- Found = get_doublets (WG, WM [Source], WM [target], doublets );
- }
- If (found ){
- List <int>: iterator first = doublets. Begin (), last = doublets. End ();
- For (; first! = Last; ++ first) cout <wt [* First] <'/N ';
- } Else {
- Cout <"no solution./N ";
- }
- }
- Return 0;
- }