1. 程式人生 > >『嗨威說』數據結構 - 第四章學習內容小結

『嗨威說』數據結構 - 第四章學習內容小結

hang oid aps 大寫轉小寫 small hat 數組 正式 das

  一道天梯賽搞得全場人崩潰的題,幾乎現場就沒幾個人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,dont 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,1000);
        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] = \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<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] = \0;
    else dealing[count] = \0;
    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] != \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<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] = \0;
    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 == \0) 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[1001];
int count;
char temp[1001];
int tMark[1001];
int main()
{
    scanf("%d",&times);
    getchar();
    while(times--)
    {
        memset(temp,0,sizeof(temp));
        memset(tMark,0,sizeof(tMark));
        cin.getline(temp,1000);
        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] = \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<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] = \0;
    else dealing[count] = \0;
    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] != \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<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] = \0;
    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 == \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

『嗨威說』數據結構 - 第四章學習內容小結