1078 字符串壓縮與解壓(PAT (Basic Level) Practice)

題目

文本壓縮有很多種方法,這里我們只考慮最簡(jiǎn)單的一種:把由相同字符組成的一個(gè)連續(xù)的片段用這個(gè)字符和片段中含有這個(gè)字符的個(gè)數(shù)來(lái)表示。例如 ccccc 就用 5c 來(lái)表示。如果字符沒(méi)有重復(fù),就原樣輸出。例如 aba 壓縮后仍然是 aba。

解壓方法就是反過(guò)來(lái),把形如 5c 這樣的表示恢復(fù)為 ccccc。

本題需要你根據(jù)壓縮或解壓的要求,對(duì)給定字符串進(jìn)行處理。這里我們簡(jiǎn)單地假設(shè)原始字符串是完全由英文字母和空格組成的非空字符串。

輸入格式:

輸入第一行給出一個(gè)字符,如果是 C 就表示下面的字符串需要被壓縮;如果是 D 就表示下面的字符串需要被解壓。第二行給出需要被壓縮或解壓的不超過(guò) 1000 個(gè)字符的字符串,以回車(chē)結(jié)尾。題目保證字符重復(fù)個(gè)數(shù)在整型范圍內(nèi),且輸出文件不超過(guò) 1MB。

輸出格式:

根據(jù)要求壓縮或解壓字符串,并在一行中輸出結(jié)果。

輸入樣例 1:

C
TTTTThhiiiis isssss a   tesssst CAaaa as

輸出樣例 1:

5T2h4is i5s a3 te4st CA3a as

輸入樣例 2:

D
5T2h4is i5s a3 te4st CA3a as10Z

輸出樣例 2:

TTTTThhiiiis isssss a   tesssst CAaaa asZZZZZZZZZZ

通過(guò)代碼(極致壓行版)

#include <iostream>
#include <ctype.h>
using namespace std;
void Cprint(int& count, char a) {//注意count是引用變量
    if (count != 1) cout << count;
    cout << a;
    count = 0;
}
int main () {
    string str, c;
    int i = 0, count = 1;//i是解碼的循環(huán)變量,控制下標(biāo)。count是壓縮過(guò)程中記錄重復(fù)字符出現(xiàn)次數(shù)的
    getline(cin, c); getline(cin, str);//輸入
    if (c == "C") {
        for (int j = 1; j < str.length(); j++, count++)//每次循環(huán)count++
            if (str[j - 1] != str[j]) Cprint(count, str[j - 1]);//如果遇到一個(gè)字符和前一個(gè)不一樣,輸出,讓count歸零
        Cprint(count, str[str.length() - 1]);//輸出最末尾的一個(gè)或一串
    } else if (c == "D") {
        if (!isdigit(str[i])) cout << str[i++];//第一個(gè)不是數(shù)字,直接輸出,i++訪(fǎng)問(wèn)下一個(gè)字符
        for (int n = 0; i < str.length(); n = 0, i++) {//n為每個(gè)字符前的數(shù)字
            for (; i < str.length() && isdigit(str[i]); n *= 10, n += (str[i++] - '0'));//如果是數(shù)字,就把數(shù)字字符轉(zhuǎn)換成數(shù),這里不是雙層for循環(huán)嵌套,這個(gè)for循環(huán)后有一個(gè)分號(hào)
            for (int j = 0; j < (n == 0 ? 1 : n); j++) cout << str[i];//循環(huán)輸出字符,如果沒(méi)有遇到數(shù)字,n為0,就輸出一次
        }
    }
    return 0;
}

通過(guò)代碼

#include <iostream>
#include <algorithm>
#include <ctype.h>
using namespace std;
struct out { char c; int n; };
void C () {
    string str;
    getline(cin, str);
    int n = str.length();
    out data[n] = {0};
    char last = -1;
    int count = -1;
    for (int i = 0; i < n; i++) {
        if (str[i] != last)
            data[++count].c = str[i];
        data[count].n++;
        last = str[i];
    }
    for (int i = 0; i < count + 1; i++) {
        if (data[i].n != 1)
            cout << data[i].n;
        cout << data[i].c;
    }
}
void D () {
    string str;
    getline(cin, str);
    int i = 0;
    if (!isdigit(str[i]))
        cout << str[i++];
    while (i < str.length()) {
        int n = 0;
        while (i < str.length() && isdigit(str[i])) {
            n *= 10;
            n += str[i++] - '0';
        }
        for (int j = 0; j < n; j++)
            cout << str[i];
        i++;
        while ( i < str.length() && !isdigit(str[i]))
            cout << str[i++];
    }
}
int main () {
    char c;
    scanf("%c%*c", &c);
    if (c == 'C') C();
    else D();
    return 0;
}

思路與注意

  1. coding(壓縮)一個(gè)函數(shù),decoding(解壓)一個(gè)函數(shù)分別處理

  2. 兩個(gè)函數(shù)統(tǒng)一使用getline,main函數(shù)里面要吃掉第一行的換行符

  3. 對(duì)于coding過(guò)程

    1. 定義一個(gè)結(jié)構(gòu)體數(shù)組,儲(chǔ)存字符與個(gè)數(shù)。數(shù)組長(zhǎng)度為輸入string的長(zhǎng)度(如果輸入的string不能壓縮,正好夠用)

    2. 遍歷一遍string,如果字符和前一個(gè)字符一樣,那么當(dāng)前結(jié)構(gòu)體(變量)的字符個(gè)數(shù)++,一旦改變,存到下一個(gè)結(jié)構(gòu)體中。

    3. 輸出結(jié)構(gòu)體,先輸出個(gè)數(shù)(大于1才輸出),再輸出這個(gè)字符

  4. 對(duì)于decoding過(guò)程

    1. 先判斷第一個(gè)字符,如果是字母直接輸出這個(gè)字母,然后字符串的“指針”向后移。

    2. 進(jìn)入循環(huán),循環(huán)的操作為,得到數(shù)字,輸出數(shù)字后的字母,然后輸出后面的單個(gè)字母,直到遇到下一個(gè)數(shù)字,進(jìn)入下一次循環(huán),或者遇到字符串結(jié)束,那就結(jié)束。

    3. 注意不要用isalpha()函數(shù)(考慮空格的存在)

反思與評(píng)價(jià)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容