列表

详情


DD13. 最短字符编码

描述

给定一个非空字符串, 按照如下方式编码, 使得编码后长度最小, 返回编码后的长度: 
编码规则为: k[encoding_string], 表示重复k次encoding_strng, 
例如'abcdefabcdefabc'可表示为'2[abcdef]abc', 但是'aaa'仅能编码成'aaa', 
因为len('3[a]')>len('aaa').
补充:
1. k为正整数, []内的encoding_string不得含有空格不得为空;
2. []内的encoding_string 本身可以为编码过的字符串, 例如'abcdabcdeabcdabcde' 可以编码为 '2[abcdabcde]'(编码后长度从18减少到12), []内的'abcdabcde'又可以编码为 '2[abcd]e', 最终编码为 '2[2[abcd]e]', 编码后长度为11, 应返回11; 这个编码路径也能是: 'abcdabcdeabcdabcde' -> '2[abcd]e2[abcd]e' -> '2[2[abcd]e]';
2. 输入字符串为全小写英文字母, 长度<=160;
3. 如果编码后长度没有更小, 则保留原有字符串;

输入描述

一行数据, 表示输入字符串

输出描述

输出一个字符串表示编码后长度

示例1

输入:

aaa

输出:

3

说明:

aaa,长度3

示例2

输入:

aaaaa

输出:

4

说明:

5[a],长度4

示例3

输入:

aabcaabcd

输出:

8

说明:

2[aabc]d,长度8

原站题解

C++14 解法, 执行用时: 2ms, 内存消耗: 396KB, 提交时间: 2020-08-21

#include<iostream>
#include<string>
using namespace std;

int main(){
    string str,str1,str2,str3,str4;
    cin>>str;
    int n=str.length();
    int len=0,len1=0,len2=0,len3=0,len4=0,k,t;
    int c=0;
    int l=0,r;
    
    if(n<=4){cout<<n<<endl;}
    else{
        for(int i=0;i<n;i++){
            if(str[i]==str[0]){
                c++;
            }
        }
        if(c==n){cout<<"4"<<endl;}
        else{
            for(int i=0;i<n;i++){
                for(int j=i+1;j<n;j++){
                    if(str[i]==str[j]){
                    
                        for(k=0;str[i+k]==str[j+k]&&i+k<n&&j+k<n;){
                            k++;
                        }
                        if(len<k){len=k;l=i;}
                    }
                }
            }
            str1=str.substr(l,len);
            for(int x=0;x<len;x++){
                for(int y=x+1;y<len;y++){
                    if(str1[x]==str1[y]){
                        for(t=0;str1[x+t]==str1[y+t]&&x+t<len&&y+t<len;){
                            t++;
                        }
                        if(len1<t){len1=t;l=x;}
                    }
                }
            }
            str2=str.substr(l,len1);
            for(int x=0;x<len;x++){
                for(int y=x+1;y<len;y++){
                    if(str1[x]==str1[y]){
                        for(t=0;str1[x+t]==str1[y+t]&&x+t<len&&y+t<len;){
                            t++;
                        }
                        if(len2<t){len2=t;l=x;}
                    }
                }
            }
            str3=str.substr(l,len2);
            for(int x=0;x<len;x++){
                for(int y=x+1;y<len;y++){
                    if(str1[x]==str1[y]){
                        for(t=0;str1[x+t]==str1[y+t]&&x+t<len&&y+t<len;){
                            t++;
                        }
                        if(len3<t){len3=t;l=x;}
                    }
                }
            }
            str4=str.substr(l,len3);
            for(int x=0;x<len;x++){
                for(int y=x+1;y<len;y++){
                    if(str1[x]==str1[y]){
                        for(t=0;str1[x+t]==str1[y+t]&&x+t<len&&y+t<len;){
                            t++;
                        }
                        if(len4<t){len4=t;l=x;}
                    }
                }
            }
            
            if(len1>4){cout<<n+9+5-len-len1-len2<<endl;}
            else if(len>4){cout<<n+6-len-len1<<endl;}
            else{cout<<n+3-len<<endl;}
        
        }
        
    }
    
    return 0;
}

C++ 解法, 执行用时: 3ms, 内存消耗: 376KB, 提交时间: 2020-11-07

#include <bits/stdc++.h>
using namespace std;

string F(string s){
    if(s.length() <= 4)
        return s;
    int n=s.length(), m=n/2, cnt=0, Min=INT_MAX;
    string pre, cur, lat;
    while(m>=1){
        for(int i=0;i<=n-m;i++){
            int t = 1;
            string a = s.substr(i, m), b;
            for(int j=1;j*m+m<=n;j++){
                b = s.substr(i+j*m, m);
                if(a == b)
                    t++;
                else
                    break;
            }
            int l = (n-t*m) + 3 + m;
            if(l<n && l<Min && t>1){
                Min = l;
                cnt = t;
                pre = s.substr(0, i);
                cur = s.substr(i, m);
                lat = s.substr(i + t*m);
            }
        }
        m--;
    }
    if(cnt==0)
        return s;
    return F(pre) + to_string(cnt) + "[" + F(cur) + "]" + F(lat);
}

int main(){
    string s, r;
    cin>>s;
    r = F(s);
    printf("%ld\n", r.length());
    return 0;
}

C++ 解法, 执行用时: 3ms, 内存消耗: 376KB, 提交时间: 2020-10-31

#include <bits/stdc++.h>
using namespace std;

string encoding_string(string s)
{
    if (s == "")return "";
    if (s.size() <= 4)return s;

    int len = s.size();
    int len2 = len / 2;    //重复子串的最大长度 可以分成的份数至少要2份

    int best_count = 0;//一次遍历得到的最优重复数
    int best_len = INT_MAX;//一次遍历得到的最优压缩到的长度
    string pre, cur, lat;//一次遍历得到的最优子串

    while (len2 >= 1)//重复子串长度最小为1
    {
        for (int k = 0; k <= len - len2; k++)//从第k个下标开始找重复子串
        {
            int count = 1;
            string s2 = s.substr(k, len2);
            string s3, s4;
            for (int j = 1; len2 * j + len2 <= len; j++)
            {
                s3 = s.substr(k + len2 * j, len2);
                if (s2.compare(s3) == 0)
                    count++;
                else
                    break;
            }

            int newlen = (len - count * len2) + 3 + len2;//压缩后的字符串长度
            if (newlen < len && newlen < best_len && count > 1)//如果压缩有效
            {
                best_len = newlen;
                best_count = count;
                pre = s.substr(0, k);
                cur = s.substr(k, len2);
                lat = s.substr(k + count * len2);
            }

        }
        len2--;//重复字符串长度缩短1
    }

    if (best_count == 0)
        return s;

    return encoding_string(pre) + to_string(best_count) + "[" + encoding_string(cur) + "]" + encoding_string(lat);
}
int main()
{
    string s;
    cin >> s;

    string result = "";
    result = encoding_string(s);

    cout << result.size() << endl;

    return 0;
}

C++14 解法, 执行用时: 3ms, 内存消耗: 376KB, 提交时间: 2020-08-22

#include <bits/stdc++.h>
using namespace std;

string encoding_string(string s)
{
    if (s == "")return "";
    if (s.size() <= 4)return s;

    int len = s.size();
    int len2 = len / 2;    //重复子串的最大长度 可以分成的份数至少要2份

    int best_count = 0;//一次遍历得到的最优重复数
    int best_len = INT_MAX;//一次遍历得到的最优压缩到的长度
    string pre, cur, lat;//一次遍历得到的最优子串

    while (len2 >= 1)//重复子串长度最小为1
    {
        for (int k = 0; k <= len - len2; k++)//从第k个下标开始找重复子串
        {
            int count = 1;
            string s2 = s.substr(k, len2);
            string s3, s4;
            for (int j = 1; len2 * j + len2 <= len; j++)
            {
                s3 = s.substr(k + len2 * j, len2);
                if (s2.compare(s3) == 0)
                    count++;
                else
                    break;
            }

            int newlen = (len - count * len2) + 3 + len2;//压缩后的字符串长度
            if (newlen < len && newlen < best_len && count > 1)//如果压缩有效
            {
                best_len = newlen;
                best_count = count;
                pre = s.substr(0, k);
                cur = s.substr(k, len2);
                lat = s.substr(k + count * len2);
            }

        }
        len2--;//重复字符串长度缩短1
    }

    if (best_count == 0)
        return s;

    return encoding_string(pre) + to_string(best_count) + "[" + encoding_string(cur) + "]" + encoding_string(lat);
}
int main()
{
    string s;
    cin >> s;

    string result = "";
    result = encoding_string(s);

    cout << result.size() << endl;

    return 0;
}

C++ 解法, 执行用时: 3ms, 内存消耗: 376KB, 提交时间: 2020-08-21

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main(){
    string str;
    cin>>str;
    if(str == "aaa")
        cout<<3<<endl;
    else if(str == "aaaaa")
        cout<<4<<endl;
    else if(str == "aabcaabcd")
        cout<<8<<endl;
    else if(str.size() < 50)
        cout<<11<<endl;
    else
        cout<<54<<endl;
    return 0;
}

上一题