#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <map>
#include <string>

using namespace std;

/*
     Ovo je probni tekst. 		Pa druga recenica! Pa treca? Pa cetvrta    
     
     
     Jos jedna recenica.
*/

class Tekst
{
	typedef set<unsigned> tPojavljivanja;
	typedef map<string,tPojavljivanja> tKatalogReci;
	
public:
	Tekst( char* imedat )
		{
		ifstream f(imedat);
		if( !f )
			throw string("Nije uspelo otvaranje datoteke!");
		
		CitajRecenice( f );
		PripremiKatalogReci();
		}
	
	void IspisiKatalogReci( ostream& f ) const
		{
		tKatalogReci::const_iterator 
			ri = _Reci.begin(),
			re = _Reci.end();
		for( ; ri!=re; ri++ ){
			f << ri->first << " - ";
			tPojavljivanja::const_iterator
				si = ri->second.begin(),
				se = ri->second.end();
			for( ; si!=se; si++ )
				f << *si << ' ';
			f << endl;
			}
		}
		
	void IspisiRecenice( ostream& f ) const
		{
		for( unsigned i=0; i<_Recenice.size(); i++ )
			f << i << " - " << _Recenice[i] << " (" << _Recenice[i].length() << ")" << (int)_Recenice[i][0] << endl;
		}
		
private:
	void CitajRecenice( istream& f )
		{
		string red;
		
		while( getline( f, red ) ){
			unsigned kraj = 0;
			while( kraj < red.size() - 1 ){
				// pronadjemo pocetak
				unsigned pocetak = red.find_first_not_of( " \t\r\n", kraj );
				if( pocetak == string::npos )
					break;
				// pronadjemo kraj
				kraj = red.find_first_of( ".?!", pocetak );
				if( kraj == string::npos )
					kraj = red.find_last_not_of( " \t\r\n" );
				kraj++;
				// izdvojimo recenicu i zapamtimo je
				_Recenice.push_back( red.substr( pocetak, kraj-pocetak ) );	
				}
			}
		}
		
	void PripremiKatalogReci()
		{
		string slova = "abcdefghijklmnopqrstuvwxyz";
		for( unsigned i=0; i<_Recenice.size(); i++ ){
			string recenica = _Recenice[i];
			for( unsigned i=0; i<recenica.size(); i++ )
				if( recenica[i]>='A' && recenica[i]<='Z' )
					recenica[i] += 'a' - 'A';
			unsigned kraj = 0;
			while( kraj < recenica.size() - 1 ){
				// pronadjemo pocetak
				unsigned pocetak = recenica.find_first_of( slova, kraj );
				if( pocetak == string::npos )
					break;
				// pronadjemo kraj
				kraj = recenica.find_first_not_of( slova, pocetak );
				if( kraj == string::npos )
					kraj = recenica.size();
				// izdvojimo rec i zapamtimo je
				_Reci[recenica.substr( pocetak, kraj-pocetak )].insert(i);
				}
			}
		}
		
	vector<string>	_Recenice;
	tKatalogReci	_Reci;
};

void pretrazivanjeTeksta( char* imedat )
{
	Tekst t(imedat);
	t.IspisiRecenice( cout );	
	t.IspisiKatalogReci( cout );	
}

main( int argc, char** argv )
{
	try	{
		if( argc < 2 )
			throw string( "Nedostaje naziv datoteke!" );
		pretrazivanjeTeksta( argv[1] );
		}
	catch( const string& s ){
		cerr << "GRESKA: " << s << endl;
		}
	return 0;	
}
