『嗨威说』数据结构 - 第四章学习内容小结

  一道天梯赛搞得全场人崩溃的题,几乎现场就没几个人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)
    {
        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] = '\0';
    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)
    {
        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] = '\0';
    else dealing[count] = '\0';
    memset(temp,0,sizeof(temp));
    strcpy(temp,dealing);
}

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

 

 

    5* bigToSmall函数的实现:

void bigToSmall()//实际上可以用tolower代替 
{
    for(int i = 0;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)
    {
        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] != '\0' && !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)
    {
        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] = '\0';
    memset(temp,0,sizeof(temp));
    strcpy(temp,dealing);
}

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

 

 

    8* changeQ的函数实现:

void changeQ()
{
    for(int i = 0;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 == '\0') mark = 1;
    return mark;
}

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

 

二、完整代码展示:

#include
#include<string.h>
#include
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)
    {
        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] = '\0';
    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)
    {
        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] = '\0';
    else dealing[count] = '\0';
    memset(temp,0,sizeof(temp));
    strcpy(temp,dealing);
}

void bigToSmall()//实际上可以用tolower代替 
{
    for(int i = 0;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)
    {
        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] != '\0' && !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)
    {
        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] = '\0';
    memset(temp,0,sizeof(temp));
    strcpy(temp,dealing);
}

void changeQ()
{
    for(int i = 0;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 == '\0') 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

 

你可能感兴趣的:(『嗨威说』数据结构 - 第四章学习内容小结)