AT—次世代SNS 题解

· · 题解

题外话:这道题原来的题号是 \texttt{AT999}

题目传送门

更好的阅读体验?

题意:

给一行一个字符串,其中只包含小写字母,空格和 @@ 之后接字母的情况才合法,求被 @ 的人的名字。

思路:

  1. 先比较首字符的大小(按照 \texttt{ASCII} 码的大小)。
  2. 如果首字母不相等,可以直接按照给定标准排序(就是自己写的函数,默认由小到大)。
  3. 若相等,则按照 2 的方法继续判断下一个字符,直到有一个字符串的所有字符都判断完了,此时长度短的小于长度长的,按照给定标准排序。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
string s,ans[101];//ans存被 @ 的人的名字
int tot;//存答案数量
int main()
{
    while(cin>>s)//一直读一个单词,可以避免很多麻烦
    {
        int nw1=s.find('@'),flag=0;
        //nw1 是找 '@' 字符的位置
        //flag 标记是否搜到最后
        while(nw1!=-1)//有 '@'
        {
            int nw2=s.find('@',nw1+1);
            //从 nw1 的下一个字符开始,寻找 '@'
            if(nw2==-1)//没有 @' 了
            {
                nw2=s.size();
                //为了使下文的 substr 不用特判
                //在全文的末尾再加一个 '@'
                //这时 '@' 的位置就是 s.size()
                flag=1;//标记已经搜到了最后
            }

            string wait=s.substr(nw1+1,nw2-(nw1+1));
            tot++;
            ans[tot]=wait;
            //wait 等待判断是否有重复的人名
            //先假设没有重复,后面再判断

            if(wait.size()==0)
            {
                //不合法情况之一:
                //是空串
                tot--;
                //不合法,数量减 1
            }

            for(int i=1;i<=tot-1;i++)       
            {
                if(ans[i]==wait)
                {
                    //不合法情况之二:
                    //有重复
                    tot--;
                    //不合法,数量减 1
                    break;
                    //不用继续判断了,跳出循环
                }
            }
            if(flag)  break;//搜到末尾了,打破循环
            nw1=nw2;
            //下一次开始判断的位置
            //就是这次判断结束的位置
        }
    }

    sort(ans+1,ans+tot+1);
    //sort 默认就是按字典序由小到大排序

    for(int i=1;i<=tot;i++)
    {
        if(ans[i].size()!=0)
        {
            //如果这个字符串不是空的,就输出
            cout<<ans[i]<<endl;
            //一行一个名字,AT 的题最后需要换行
        }
    }

    return 0;
}      

最快 5ms