POJ 2176 Folding (字串)

來源:互聯網
上載者:User

題意:個你一個字串將其進行壓縮,使得壓縮後的串長度最短。

壓縮規則:

  • A sequence that contains a single character from 'A' to 'Z' is considered to be a folded sequence. Unfolding of this sequence produces the same sequence of a single character itself. 
  • If S and Q are folded sequences, then SQ is also a folded sequence. If S unfolds to S' and Q unfolds to Q', then SQ unfolds to S'Q'. 
  • If S is a folded sequence, then X(S) is also a folded sequence, where X is a decimal representation of an integer number greater than 1. If S unfolds to S', then X(S) unfolds to S' repeated X times.

例如:AAAAAAAAAABABABCCD 壓縮為 10(A)2(BA)B2(C)D


題解:區間DP,類似於矩陣鏈乘。對每個區間進行處理的時候,相當於對該區間進行打包,記錄下該區間的基本模式串,以及該基本模式串的重複次數,例如:AAAAA => 5(A),基本模式串是"A",重複次數為5。我們應該盡量取重複次數多的打包方式,這樣可以最大限度的與左右區間進行合并從而減少字串的總長度。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct Segment{    int l, r; //l是基本模式串的長度,r是重複次數    char s[101]; //基本模式串} dp[101][101];int diglen(int num) {    if(num < 10) return 1;    else if(num < 100) return 2;    else return 3;}Segment pack(const Segment &seg) //進行打包{    Segment ret;    int digNum = diglen(seg.r); //求數位字元個數    if(seg.l * seg.r < seg.l + digNum + 2) //+2是因為括弧有兩個字元    {        ret.r = 1;        ret.l = seg.l * seg.r;        strcpy(ret.s, seg.s);        for(int i = 1; i < seg.r; i++)            strcat(ret.s, seg.s);    }    else    {        ret.r = 1;        ret.l = seg.l + digNum + 2;        sprintf(ret.s, "%d(%s)", seg.r, seg.s);    }    return ret;}int packlen(const Segment &seg) //返回打包後的最小長度{    return min(seg.l * seg.r, seg.l + 2 + diglen(seg.r));}int linklen(const Segment &seg1, const Segment &seg2, int &linkr) //返回將兩個區間合并後的最小長度{    int len;    if(seg1.l == seg2.l && 0 == strcmp(seg1.s, seg2.s)) //基本模式串一樣則只需將重複次數相加    {        linkr = seg1.r + seg2.r;        len = seg1.l;    }    else     {        linkr = 1;        len = packlen(seg1) + packlen(seg2);    }    return min(linkr * len, len + 2 + diglen(linkr));}Segment link(const Segment &seg1, const Segment &seg2) //將兩個區間的串進行合并{    Segment ret;    if(seg1.l == seg2.l && 0 == strcmp(seg1.s, seg2.s))    {        strcpy(ret.s, seg1.s);        ret.l = seg1.l;        ret.r = seg1.r + seg2.r;    }    else //基本模式串不同則需要先分別對兩個區間進行打包,然後串連起來    {        Segment tmp1 = pack(seg1);         Segment tmp2 = pack(seg2);        strcpy(ret.s, tmp1.s);        strcat(ret.s, tmp2.s);        ret.l = tmp1.l + tmp2.l;        ret.r = 1;    }    return ret;}int main(){    char str[110];    while(scanf("%s",str) != EOF)    {        int i, j, k;        int len = strlen(str);        for(i = 0; i < len; i++)        {            dp[i][i].l = dp[i][i].r = 1;            dp[i][i].s[0] = str[i];            dp[i][i].s[1] = '\0';        }        int tmpl, tmpr;        int markl, markr, markj;        for(k = 1; k < len; k++)        {            for(i = 0; i + k < len; i++)            {                markj = i;                markl = linklen(dp[i][i], dp[i+1][i+k], markr);                for(j = i + 1; j < i + k; j++)                {                    tmpl = linklen(dp[i][j], dp[j+1][i+k], tmpr);                    if(tmpl < markl || (tmpl == markl && tmpr > markr))                        markl = tmpl, markr = tmpr, markj = j;                }                dp[i][i+k] = link(dp[i][markj], dp[markj+1][i+k]);            }        }        Segment tmp = pack(dp[0][len-1]);        printf("%s\n",tmp.s);    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.