STL太慢了,把这一章的例题做完就ok了,还有三道
这道题我一开始的思路是在每一个col里比较每个row,如果有两个相同的row,就去判断与之对应的别的行的row是否相等。
如果使用上面的这种方式,实现的策略是一个一个对比的话,时间复杂度是n^2*m,是非常大的,但如果将每行的元素都保存起来,保存到map中去,那么时间复杂度是n*logn*m,卧槽这么简单的方式我刚刚没有想到。即:如果要在一堆元素里,找相同的元素,可以使用map来寻找,省去了一个一个比较的过程,但是这种方式仅仅适合于相同的元素是唯一的,如果不唯一,那么就需要在map的第二个元素上添一个结构体或者set(用了set之后会变的很慢,因为又得寻找一次),来保存多个r。时间复杂度降低为nlogn而不是n^2;
刘汝佳的方式是,对比两列的内容,然后把两行的东西,凑成一个pair(这个东西我从来没有见过,算是学到了点东西了吧),这样的时间复杂度是m^2*n*logn
下面贴上我模仿的刘汝佳版本的代码
//第一个思路,扫描各列,在当前列中遇到相同的字符串的时候,查看其它列中对应的行是不是也是相同的,时间复杂度为n^2*m //第二种刘汝佳的思路是,直接枚举各行,即一次扫两行,判断两行内容组成的二元组是否曾出现过,时间复杂度为n*m^2 //两种都写一下啊,而且第二种思路还有一个小技巧可以节约时间,就是将字符串转换成整数,在查找两行内容组成的二元组是否出现过的时候,会发生字符串的比较 //字符串的比较是非常消耗时间的,尤其是在这样的字符串很多的时候,转换成整数后的比较就简单了很多了。 //我感觉这个技巧其实是一个伪命题,因为在转换的时候,也是要比较的啊???而且还多了一次整数的比较。或者是因为凑起来的字符串长了很多? #include<iostream> #include<string> #include<map> #include<ctime> #include<sstream> using namespace std; typedef pair<int ,int> PII; int row,col,index; int database[10005][14]; map<string,int>Map; map<PII,int>Map_compare; int s_id(string s) { if(Map.count(s)) return Map[s]; else { Map[s]=index; index++; return index-1; } } void compare() { for(int c = 1;c <= col - 1;c++) { for(int c_next= c+1;c_next<=col;c_next++) { Map_compare.clear(); index = 0; for(int r = 1;r <= row;r++) { int x1 = database[r][c]; int x2 = database[r][c_next]; PII p = make_pair(x1,x2); //cout<<x1<<" "<<x2<<endl; if(Map_compare.count(p))//之前出现了 { printf("NO\n"); printf("%d %d\n",Map_compare[p],r); printf("%d %d\n",c,c_next); return; } else { Map_compare[p]=r; } } } } printf("YES\n"); } int main() { #ifdef local freopen("input.txt","r",stdin); freopen("output1.txt","w",stdout); #endif string line; while(getline(cin,line)) { Map.clear(); stringstream ss(line); ss>>row>>col; //getchar(); //string line; //printf("%d%d\n",row,col); for(int r = 1;r <= row;r++) { getline(cin,line); int pos=0,last; for(int c = 1;c <= col;c++) { last = line.find(',',pos); if(last == string::npos) last = line.length(); database[r][c] = s_id(line.substr(pos,last - pos)); //cout<<database[r][c]<<endl; pos = last + 1; } } compare(); } printf("%lf",(double)clock()/CLOCKS_PER_SEC); return 0; }
第二种思路由于同一行中相同的字符串出现了多次,所以导致时间变得很慢。
在这道题中还学到的东西是:一般不要使用sstream,因为会非常的慢,可以使用s.find()函数以及s.substr(pos,len)函数来返回一个字串。
还有就是如果要使用getline()的话,就全部使用getline(),虽然以前说过,但这次还是犯了这样的错误了。
大的方向的算法复杂度满足就可以了,至于一些细小的方面,没有必要耗费太多的精力,因为有时候减少的时间很少,另外会让编程的复杂度升高。