zoukankan      html  css  js  c++  java
  • 『嗨威说』数据结构

      一道天梯赛搞得全场人崩溃的题,几乎现场就没几个人AC,现在回头看看,真的很考细节耐心地题目。

    -----------------------------题目-----------------------------

    1. 无论用户说什么,首先把对方说的话在一行中原样打印出来;
    2. 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
    3. 把原文中所有大写英文字母变成小写,除了 I;
    4. 把原文中所有独立的 I 和 me 换成 you;
    5. 把原文中所有的问号 ? 换成惊叹号 !;
    6. 把原文中所有独立的 can you 换成 I can —— 这里“独立”是指被空格或标点符号分隔开的单词;
    7. 在一行中输出替换后的句子作为 AI 的回答

    输入样例:

    6
    Hello ?
     Good to chat   with you
    can   you speak Chinese?
    Really?
    Could you show me 5
    What Is this prime? I,don 't know

    输出样例:

    Hello ?
    AI: hello!
     Good to chat   with you
    AI: good to chat with you
    can   you speak Chinese?
    AI: I can speak chinese!
    Really?
    AI: really!
    Could you show me 5
    AI: could you show you 5
    What Is this prime? I,don 't know
    AI: what Is this prime! you,don't know

    -----------------------------题目-----------------------------

    一、正式题解:

        1* 函数原型声明:

    void deleteSymbolSpace();
    void deleteSpace();
    void bigToSmall();
    void changePersonY();
    void changePersonI();
    void changeQ();
    bool isIndenpend(char temp);

          deleteSymbolSpace —— 删除符号前的空格

          deleteSpace —— 删除多余空格

          bigToSmall —— 将大写转小写

          changePersonY —— 改变人称You

          changePersonI —— 改变人称I me

          changeQ —— 问号改为感叹号

          isIndenpend —— 判断是否独立函数

        2* 主函数框架构建:

    int main()
    {
        scanf("%d",&times);
        getchar();
        while(times--)
        {
            memset(temp,0,sizeof(temp));
            memset(tMark,0,sizeof(tMark));
            cin.getline(temp,2000);
            puts(temp);
            changeQ();
            bigToSmall();
            deleteSpace();
            changePersonY();
            changePersonI();
            deleteSpace();
            deleteSymbolSpace();
            printf("AI: ");
            puts(temp);
        }
        return 0;
    }

          抛开细节的实现方式,从大局角度思考程序的运行方式。

        3*deleteSymbolSpace的实现:

    void deleteSymbolSpace()
    {
        memset(dealing,0,sizeof(dealing));
        count = 0;
        for(int i = 0;i<strlen(temp);i++)
        {
            if(temp[i] == 32)
            {
                int flag = 0;
                if(temp[i+1]>=33 && temp[i+1]<=47) flag = 1;
                else if(temp[i+1]>=58 && temp[i+1]<=64) flag = 1;
                else if(temp[i+1]>=91 && temp[i+1]<=96) flag = 1;
                else if(temp[i+1]>=123 && temp[i+1]<=126) flag = 1;
                
                if(flag == 1)
                {
                    dealing[count] = temp[i+1];
                    count++;
                    i=i+1;
                }
                else
                {
                    dealing[count] = temp[i];
                    count++;
                }
            }
            else
            {
                dealing[count] = temp[i];
                count++;
            }
        }
        dealing[count] = '';
        memset(temp,0,sizeof(temp));
        strcpy(temp,dealing);
    }

        因为刚开始不知道判断字母和数字的函数,所以干脆直接简单粗暴,ASCII扫独立。

        4* deleteSpace函数的实现:

    void deleteSpace()
    {
        int start = 0;
        int space = 0;
        memset(dealing,0,sizeof(dealing));
        count = 0;
        for(int i = 0;i<strlen(temp);i++)
        {
            if(start == 0 && temp[i] == 32) continue;
            else if(start == 0 && temp[i] != 32)
            {
                start = 1;
                dealing[count] = temp[i];
                count++;
                continue;
            }
            
            if(temp[i] == 32)
            {
                if(space == 1) continue;
                if(tMark[i] == 1) continue;
                space = 1;
                dealing[count] = 32;
                count++;
            }
            else
            {
                space = 0;
                dealing[count] = temp[i];
                count++;
            }
        }
        if(dealing[count-1] == 32) dealing[count-1] = '';
        else dealing[count] = '';
        memset(temp,0,sizeof(temp));
        strcpy(temp,dealing);
    }

        核心思路很简单,就是拿一个新数组去存新的结果,通过打标记判断是否是句头空行。

        5* bigToSmall函数的实现:

    void bigToSmall()//实际上可以用tolower代替 
    {
        for(int i = 0;i<strlen(temp);i++)
        {
            if( temp[i] >= 65 && temp[i] <= 90)
            {
                if(temp[i] == 'I') continue;
                temp[i] = temp[i] + 32;
            }
        }
    }

          这里也是因为不知道有tolower这个魔鬼函数,所以依旧简单粗暴,暴力用ASCII解决问题。

        6* changePersonY函数的实现:

    void changePersonY()
    {
        for(int i = 0;i<strlen(temp);i++)
        {
            int flag = -1;
            if(i != 0 && !isIndenpend(temp[i-1])) continue;
            if(temp[i] == 'c' && temp[i+1] == 'a' && temp[i+2] == 'n') flag = 3;
            else if(temp[i] == 'c' && temp[i+1] == 'o' && temp[i+2] == 'u' && temp[i+3] == 'l' && temp[i+4] == 'd') flag = 5;
            
            if(flag != -1)
            {
                int mark = 0;
                if(temp[i+flag]>=32 && temp[i+flag]<=47) mark = 1;
                else if(temp[i+flag]>=58 && temp[i+flag]<=64) mark = 1;
                else if(temp[i+flag]>=91 && temp[i+flag]<=96) mark = 1;
                else if(temp[i+flag]>=123 && temp[i+flag]<=126) mark = 1;
                if(mark == 1)
                {
                    if(temp[i+flag+mark] == 'y' && temp[i+flag+mark+1] == 'o' && temp[i+flag+mark+2] == 'u')
                    {
                        if(temp[i+flag+mark+3] != '' && !isIndenpend(temp[i+flag+mark+3])) continue;
                        temp[i] = 'I';
                        tMark[i] = 1;
                        temp[i+1] = temp[i+flag];
                        if(flag == 3)
                        {
                            temp[i+2] = 'c';
                            temp[i+3] = 'a';
                            temp[i+4] = 'n';
                        }
                        else if(flag == 5)
                        {
                            temp[i+2] = 'c';
                            temp[i+3] = 'o';
                            temp[i+4] = 'u';
                            temp[i+5] = 'l';
                            temp[i+6] = 'd';
                        }
                        
                        temp[i +flag+2] = ' ';
                        temp[i +flag+3] = ' ';
                        tMark[i +flag+2] = tMark[i +flag+3] = 1;
                        i = i +flag+3;
                    }
                }
            }
        }
    }

         转换人称是所有限制条件最麻烦最难的地方,需要注意打上标记,因为对string还是有点小反感,虽然挺好用,但是习惯用char进行单个强行处理,所以这里一直是用char来处理的~ 

        7* changePersonI函数的实现:

    void changePersonI()
    {
        memset(dealing,0,sizeof(dealing));
        count = 0;
        for(int i = 0;i<strlen(temp);i++)
        {
            if(temp[i] == 'I' && isIndenpend(temp[i+1]) && tMark[i] == 0)
            {
                if(i != 0 && !isIndenpend(temp[i-1])) 
                {
                    dealing[count] = temp[i];
                    count++;
                    continue;
                }
                dealing[count] = 'y';
                dealing[count+1] = 'o';
                dealing[count+2] = 'u';
                count += 3;
            }
            else if(temp[i] == 'm' && temp[i+1] == 'e' && isIndenpend(temp[i+2]))
            {
                if(i != 0 && !isIndenpend(temp[i-1]))
                {
                    dealing[count] = temp[i];
                    count++;
                    continue;
                }
                dealing[count] = 'y';
                dealing[count+1] = 'o';
                dealing[count+2] = 'u';
                count += 3;
                i = i + 1;
            }
            else
            {
                dealing[count] = temp[i];
                count++;
            }
        }
        dealing[count] = '';
        memset(temp,0,sizeof(temp));
        strcpy(temp,dealing);
    }

          这里尤其需要注意,不能把已经换过的人称再换一次,所以需要对标记进行判断。

        8* changeQ的函数实现:

    void changeQ()
    {
        for(int i = 0;i<strlen(temp);i++)
            if(temp[i] == '?')
                temp[i] = '!';
    }

          尽管函数简单,但尽量单独列出,使程序更加结构化。

        9* isIndenpend函数的实现:

    bool isIndenpend(char temp)
    {
        int mark = 0;
        if(temp>=32 && temp<=64) mark = 1;
        else if(temp>=91 && temp<=96) mark = 1;
        else if(temp>=123 && temp<=126) mark = 1;
        else if(temp == '') mark = 1;
        return mark;
    }

          暴力ASCII码解决,虽然不是最佳的处理方式。

    二、完整代码展示:

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    
    //------------------------
    void deleteSymbolSpace();
    void deleteSpace();
    void bigToSmall();
    void changePersonY();
    void changePersonI();
    void changeQ();
    bool isIndenpend(char temp);
    //------------------------
    
    int times;
    char dealing[2001];
    int count;
    char temp[2001];
    int tMark[2001];
    int main()
    {
        scanf("%d",&times);
        getchar();
        while(times--)
        {
            memset(temp,0,sizeof(temp));
            memset(tMark,0,sizeof(tMark));
            cin.getline(temp,2000);
            puts(temp);
            changeQ();
            bigToSmall();
            deleteSpace();
            changePersonY();
            changePersonI();
            deleteSpace();
            deleteSymbolSpace();
            printf("AI: ");
            puts(temp);
        }
        return 0;
    }
    
    void deleteSymbolSpace()
    {
        memset(dealing,0,sizeof(dealing));
        count = 0;
        for(int i = 0;i<strlen(temp);i++)
        {
            if(temp[i] == 32)
            {
                int flag = 0;
                if(temp[i+1]>=33 && temp[i+1]<=47) flag = 1;
                else if(temp[i+1]>=58 && temp[i+1]<=64) flag = 1;
                else if(temp[i+1]>=91 && temp[i+1]<=96) flag = 1;
                else if(temp[i+1]>=123 && temp[i+1]<=126) flag = 1;
                
                if(flag == 1)
                {
                    dealing[count] = temp[i+1];
                    count++;
                    i=i+1;
                }
                else
                {
                    dealing[count] = temp[i];
                    count++;
                }
            }
            else
            {
                dealing[count] = temp[i];
                count++;
            }
        }
        dealing[count] = '';
        memset(temp,0,sizeof(temp));
        strcpy(temp,dealing);
    }
    
    
    void deleteSpace()
    {
        int start = 0;
        int space = 0;
        memset(dealing,0,sizeof(dealing));
        count = 0;
        for(int i = 0;i<strlen(temp);i++)
        {
            if(start == 0 && temp[i] == 32) continue;
            else if(start == 0 && temp[i] != 32)
            {
                start = 1;
                dealing[count] = temp[i];
                count++;
                continue;
            }
            
            if(temp[i] == 32)
            {
                if(space == 1) continue;
                if(tMark[i] == 1) continue;
                space = 1;
                dealing[count] = 32;
                count++;
            }
            else
            {
                space = 0;
                dealing[count] = temp[i];
                count++;
            }
        }
        if(dealing[count-1] == 32) dealing[count-1] = '';
        else dealing[count] = '';
        memset(temp,0,sizeof(temp));
        strcpy(temp,dealing);
    }
    
    void bigToSmall()//实际上可以用tolower代替 
    {
        for(int i = 0;i<strlen(temp);i++)
        {
            if( temp[i] >= 65 && temp[i] <= 90)
            {
                if(temp[i] == 'I') continue;
                temp[i] = temp[i] + 32;
            }
        }
    }
    
    void changePersonY()
    {
        for(int i = 0;i<strlen(temp);i++)
        {
            int flag = -1;
            if(i != 0 && !isIndenpend(temp[i-1])) continue;
            if(temp[i] == 'c' && temp[i+1] == 'a' && temp[i+2] == 'n') flag = 3;
            else if(temp[i] == 'c' && temp[i+1] == 'o' && temp[i+2] == 'u' && temp[i+3] == 'l' && temp[i+4] == 'd') flag = 5;
            
            if(flag != -1)
            {
                int mark = 0;
                if(temp[i+flag]>=32 && temp[i+flag]<=47) mark = 1;
                else if(temp[i+flag]>=58 && temp[i+flag]<=64) mark = 1;
                else if(temp[i+flag]>=91 && temp[i+flag]<=96) mark = 1;
                else if(temp[i+flag]>=123 && temp[i+flag]<=126) mark = 1;
                if(mark == 1)
                {
                    if(temp[i+flag+mark] == 'y' && temp[i+flag+mark+1] == 'o' && temp[i+flag+mark+2] == 'u')
                    {
                        if(temp[i+flag+mark+3] != '' && !isIndenpend(temp[i+flag+mark+3])) continue;
                        temp[i] = 'I';
                        tMark[i] = 1;
                        temp[i+1] = temp[i+flag];
                        if(flag == 3)
                        {
                            temp[i+2] = 'c';
                            temp[i+3] = 'a';
                            temp[i+4] = 'n';
                        }
                        else if(flag == 5)
                        {
                            temp[i+2] = 'c';
                            temp[i+3] = 'o';
                            temp[i+4] = 'u';
                            temp[i+5] = 'l';
                            temp[i+6] = 'd';
                        }
                        
                        temp[i +flag+2] = ' ';
                        temp[i +flag+3] = ' ';
                        tMark[i +flag+2] = tMark[i +flag+3] = 1;
                        i = i +flag+3;
                    }
                }
            }
        }
    }
    
    void changePersonI()
    {
        memset(dealing,0,sizeof(dealing));
        count = 0;
        for(int i = 0;i<strlen(temp);i++)
        {
            if(temp[i] == 'I' && isIndenpend(temp[i+1]) && tMark[i] == 0)
            {
                if(i != 0 && !isIndenpend(temp[i-1])) 
                {
                    dealing[count] = temp[i];
                    count++;
                    continue;
                }
                dealing[count] = 'y';
                dealing[count+1] = 'o';
                dealing[count+2] = 'u';
                count += 3;
            }
            else if(temp[i] == 'm' && temp[i+1] == 'e' && isIndenpend(temp[i+2]))
            {
                if(i != 0 && !isIndenpend(temp[i-1]))
                {
                    dealing[count] = temp[i];
                    count++;
                    continue;
                }
                dealing[count] = 'y';
                dealing[count+1] = 'o';
                dealing[count+2] = 'u';
                count += 3;
                i = i + 1;
            }
            else
            {
                dealing[count] = temp[i];
                count++;
            }
        }
        dealing[count] = '';
        memset(temp,0,sizeof(temp));
        strcpy(temp,dealing);
    }
    
    void changeQ()
    {
        for(int i = 0;i<strlen(temp);i++)
            if(temp[i] == '?')
                temp[i] = '!';
    }
    
    bool isIndenpend(char temp)
    {
        int mark = 0;
        if(temp>=32 && temp<=64) mark = 1;
        else if(temp>=91 && temp<=96) mark = 1;
        else if(temp>=123 && temp<=126) mark = 1;
        else if(temp == '') mark = 1;
        return mark;
    }

    三、个人反思:

        AI这道题还有待进一步优化和升级,还有一个bug没有发现,还会继续解决,重点想讲的是程序设计的架构:

        框架化的程序设计方法,是很早在Quanta冬令营中安卓JAVA的设计学习而得,由此类比过来的。我觉得,倘若要成为合格的程序设计师,出外工作的话,对框架的把握是非常重要的一个关卡,代码是否结构化明显,是否符合公司开发要求,是否易读都是程序设计过程中非常关键的地方。在安卓中,有分层WEB层、底层、数据层、素材动画层等等,选用合理的框架,能对团队的程序设计带来极大的效益,因此这个思想需要坚持并保留下来。

        接下来的学习历程吧:

        =》学习十字链表以及线性树、主席树、区间更新等ACM问题,为5月12日的广东省ACM省赛做准备

        =》学习统计学习方法,掌握模型评估、决策树、向量机等知识,为数据挖掘实验室——多模态情感分析项目组努力。

        =》前阵子七周都在英剧上花了不少时间,学习有些耽误,后续时间将慢慢追回学业,保证学业状态。

        哦对了,顺便附加ACM中的KMP模板吧,挺好用的,直接背下来用就好了~

    int KMP(char* str,char* pat)
    {
        int i,j,k;
        memset(fail,-1,sizeof(fail));
        for(i = 1;pat[i];++i)
        {
            for(k = fail[i-1];k>=0 && pat[i] != pat[k+1];k = fail[k]);
            if(pat[k+1] == pat[i]) fail[i] = k + 1;
        }
        i = j = 0;
        while(str[i] && pat[j])
        {
            if(pat[j] == str[i]) ++i,++j;
            else if(j == 0) ++i;
            else j = fail[j-1] + 1;
        }
        if(pat[j]) return 0;
        else return i-j+1;
     }
    View Code
  • 相关阅读:
    Unity3d热更新全书-加载(一)从AssetBundle说起
    Unity3D热更新全书-脚本(三) C#LightEvil语法与调试
    Unity3D热更新全书-脚本(二) 两级分化
    Unity3D热更新全书-脚本(一) 初识脚本
    Unity3D热更新全书-何谓热更新,为何热更新,如何热更新
    C#Light/Evil合体啦
    C#最良心脚本语言C#Light/Evil,XamarinWP8Unity热更新最良心方案,再次进化.
    C#Light 再推荐,顺便介绍WP8 功能展示项目
    任意两张带透明图像的一种形状过渡效果
    FileFilter
  • 原文地址:https://www.cnblogs.com/WinniyGD/p/10708279.html
Copyright © 2011-2022 走看看