2017noip普及组 T2 librian

来源:互联网 发布:linux怎么运行多线程 编辑:程序博客网 时间:2024/06/07 10:29

copy from luogu:P3955 图书管理员

题目描述

图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个 正整数。 每位借书的读者手中有一个需求码,这个需求码也是一个正整数。如果一本书的图 书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的。 小 D 刚刚当上图书馆的管理员,她知道图书馆里所有书的图书编码,她请你帮她写 一个程序,对于每一位读者,求出他所需要的书中图书编码最小的那本书,如果没有他 需要的书,请输出-1。

输入输出格式

输入格式:
输入文件的第一行,包含两个正整数 n 和 q,以一个空格分开,分别代表图书馆里 书的数量和读者的数量。

接下来的 n 行,每行包含一个正整数,代表图书馆里某本书的图书编码。

接下来的 q 行,每行包含两个正整数,以一个空格分开,第一个正整数代表图书馆 里读者的需求码的长度,第二个正整数代表读者的需求码。

输出格式:
输出文件有 q 行,每行包含一个整数,如果存在第 i 个读者所需要的书,则在第 i 行输出第 i 个读者所需要的书中图书编码最小的那本书的图书编码,否则输出-1。


看到这道题,心里满满的泪,如此简单的一道字符串模拟,我居然傻乎乎的正着比较,傻乎乎的多写了一条语句..
差了20分的一等,败在了这道noip只过了八个点的水题上

方法一:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>using namespace std;int n,q;string book[1025];string need[1025];int len_str;int compare(string a,string b)//自定义的比较字符串的函数{                             //匹配的编码返回1,否则返回-1    int lena=a.size();    int lenb=b.size();    int t=max(lena,lenb);    int k;    for(k=0;k<t;k++)        if(a[lena-k-1]!=b[lenb-k-1]) break;    if(k!=lenb) return -1;    return 1;}bool cmp(string a,string b){    int lena=a.size(),lenb=b.size();    if(lenb!=lena) return lena<lenb;    return a<b;}int main(){    scanf("%d%d",&n,&q);    for(int i=1;i<=n;i++)        cin>>book[i];    for(int i=1;i<=q;i++)    {        scanf("%d",&len_str);        cin>>need[i];    }    sort(book+1,book+n+1,cmp);//有20%的数据是从小到大排好了的,然而只是20%,所以还是要快排过一遍    for(int i=1;i<=q;i++)     //暴力枚举每个字符串    {        int k;        for(int j=1;j<=n;j++)        {            k=compare(book[j],need[i]);            if(k==1){                cout<<book[j]<<endl;//由于是从小到大快排过的,最先找到的一定是最小的,直接输出                break;            }        }        if(k==-1)            printf("-1\n"); //不匹配就输出-1好了    }    return 0;}

方法二:只是换了compare()函数,主程序没有变
noip考试的时候不正常的脑子想到的新新算法,还调试了半天,给的300的大数据都对了..
当时考试的时候写的compare函数是这样子的,有一个地方当时傻了,不知道为什么要加那一句。。
不然就ac了..不然就一等了…
还是败在了循环队列上..

int compare(string a,string b){    int s=0,x=0;    int lena=a.size(),lenb=b.size();    int j=0;//j指针指向b字符串中的元素    for(int i=0;i<lena;i++)    {        if(a[i]==b[j]) s++;//s记录匹配的单个字母的个数        else{              //不匹配的话            s=0;j=-1;      //重新初始化数据            i=x++;         //x记录下一次该从b字符串的那个位置匹配        }        if(s==lenb&&i==lena-1) return 1;//整个b字符串都为a的子串且位于a串的最后,匹配成功        //if(j==lenb-1) j=0; 没错,就是这一句,我也没看懂这是个啥!!也许是考试前循环队列看多了??        j++;//j指针往后移一位    }    return -1;//没有匹配就返回-1}

方法三:
想出来的比较快的速度,用int或者long long来做,不知道为什么有两组数据不对
感觉是数据的问题啊..从洛谷上下下来的数据都是连在一起的,疑惑字符串模拟为啥能过那组数据..

虽然速度快,可是有点点小问题,字符串能直接过不超时,还是不要用int取模比较的好

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;typedef long long ll;ll book[1025],n,q;struct tLib{    ll b,len;}need[1025];int com_int(ll a,ll b)//既然是比较两个整型,就叫com_int好啦..{    ll x=1;    for(int i=1;;i++)    {        x*=10;        ll temp=a%x;//对a取模的位数依次增加,表示从后往前的位数        if(temp==b)//直接余数与b比较,匹配返回1            return 1;        if(a%x==a)            return -1;//a%x==a的时候表明匹配已经失败,返回-1    }}int main(){    scanf("%lld%lld",&n,&q);    for(int i=1;i<=n;i++)        scanf("%lld",&book[i]);//用scanf和printf提高速度    for(int i=1;i<=n;i++)        scanf("%lld%lld",&need[i].len,&need[i].b);    sort(book+1,book+1+n);    for(int i=1;i<=q;i++)    {        int k;        for(int j=1;j<=n;j++)        {            k=com_int(book[j],need[i].b);            if(k==1){                printf("%lld\n",book[j]);                break;            }        }        if(k==-1)            printf("-1\n");    }    return 0;//再次说明这个程序只能过8个点..}
原创粉丝点击