#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

void Tokenize(const string& str,
                      vector<string>& tokens,
                      const string& delimiters = " ")
{

    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}

int main(int argc, char** argv){
	typedef pair<vector<string>, vector<string> > Bicluster;
	vector <Bicluster> mybix [2];
	
	string file1(argv[1]);
    string file2(argv[2]);
	
	for(int i=1; i <=2; i++){
      //cout<<"i = "<<i<<endl;
       string line;
       //cout<<"file1 ="<<argv[1]<<" file2 ="<<argv[2]<<endl;
       ifstream myfile(argv[i]);
       //cout<<"opening file"<<argv[i]<<endl;
       vector<Bicluster> biclusters;
	   if (myfile.is_open())
	   {
	       
		   vector<string> rows;
		   vector<string> cols;
	       int index =0;
	       while (! myfile.eof() )
	       {
	       	    getline (myfile,line);
	       	    //cout<<"index = "<<index<<endl;
	      		if(index == 0){
		      		vector<string> tokens;
	    	  		Tokenize(line, tokens);
	    	  		if(tokens.size() == 0) break;
	      			int numrows = atoi(tokens.at(0).c_str());
	      			//cout<<"numrows ="<<numrows<<endl;
	      			int numcols = atoi(tokens.at(1).c_str());
	      			//cout<<"numcols ="<<numcols<<endl;
	      			index += 1;
	      		}
	      		else if(index == 1){
	      	  		vector<string> tokens2;
			  		Tokenize(line, tokens2);
			  		for(int t=0; t < tokens2.size(); t++){
		  				rows.push_back(tokens2.at(t));
		  				//cout<<tokens2.at(t)<<"added to rows"<<endl;
		  			}
		  			index += 1;
	      		}
	      		else if(index == 2){
			  		vector<string> tokens3;
			  		Tokenize(line, tokens3);
			  		for(int tc=0; tc < tokens3.size(); tc++){
		  				cols.push_back(tokens3.at(tc));
		  				//cout<<tokens3.at(tc)<<"added to cols"<<endl;
		  			}
		  			Bicluster bix(rows,cols);
		  			biclusters.push_back(bix);
		  			mybix[i-1].push_back(bix);
		  			//cout<<"bix added and i="<<i-1<<endl;
		  			index =0;
	    		}
	   	   }
	   	   myfile.close();
	       //cout<<"file closed"<<endl;
	   }
       
	
	   //mybix[i].push_back(biclusters);
	}
    int countCommonCols =0;
    int countCommonRows =0;
    //cout<<"mybixes 0"<<mybix[0].size()<<endl;
    //cout<<"mybixes 1"<<mybix[1].size()<<endl;
	double globalscore=0;
	for(int i=0; i < mybix[0].size(); i++){
		Bicluster bics1= mybix[0].at(i);
		vector<string> rows1 = bics1.first;
		vector<string> cols1 = bics1.second;
		double maxscore=0;
		for(int j=0; j< mybix[1].size(); j++){
			Bicluster bics2= mybix[1].at(j);
			vector<string> rows2 = bics2.first;
			vector<string> cols2 = bics2.second;
		    //int small = rows1 > rows2 ? rows2 : rows1;
            countCommonRows =0;
		    for(int ri=0; ri < rows1.size(); ri++){
		    	for(int rj=0; rj<rows2.size(); rj++){
		    		if(rows1.at(ri) == rows2.at(rj)){
		    			countCommonRows += 1;
		    			//cout<<"common rows ="<<countCommonRows<<endl;
		    			break;
		    		}
		    	}
		    }
	        countCommonCols =0;
		    for(int ci=0; ci < cols1.size(); ci++){
		    	for(int cj=0; cj<cols2.size(); cj++){
		    		if(cols1.at(ci) == cols2.at(cj)){
		    			countCommonCols +=1;
		    			//cout<<"common cols ="<<countCommonCols<<endl;
		    			break;
		    		}
		    	}
		    }
		    //cout<<"common cols = "<<countCommonCols<<endl;
			//cout<<"commmon rows ="<<countCommonRows<<endl;
			//cout<<" i "<<i<<" j= "<<j<<endl;
			int unioncols = cols1.size()+cols2.size()-countCommonCols;
			int unionrows = rows1.size()+rows2.size()-countCommonRows;
			double score = (double)(countCommonCols+countCommonRows)/(double)(unioncols+unionrows);
			maxscore = score >= maxscore ? score:maxscore;
			//cout<<"max score = "<<maxscore<<endl;
		}
		
		
		globalscore += maxscore;
		//cout<<"globalscore ="<<globalscore<<endl;
	}
	globalscore = globalscore/mybix[0].size();
	cout<<"Score = "<<globalscore<<endl;
}
