UVA1592

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(),虽然以前说过,但这次还是犯了这样的错误了。

大的方向的算法复杂度满足就可以了,至于一些细小的方面,没有必要耗费太多的精力,因为有时候减少的时间很少,另外会让编程的复杂度升高。

转载于:https://www.cnblogs.com/TorettoRui/p/10422418.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值