zoukankan      html  css  js  c++  java
  • b_lg_字符串折叠(折叠与不折叠取最优)

    给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。
    输入格式
    仅一行,即字符串S,长度保证不超过100。
    输出格式
    仅一行,即最短的折叠长度。

    输入
    NEERCYESYESYESNEERCYESYESYES
    输出
    14
    说明/提示
    一个最短的折叠为:2(NEERC3(YES))
    

    方法一:dp

    折叠不一定比折叠后的字符串更短,所以这里有两种选择:

    • 折叠:需要枚举的子串是否有循环节,如果有,计算长度即可
    • 不折叠,则 f[i][j]=min(f[i][j], f[i][k]+f[k+1][j])
    #include<bits/stdc++.h>
    using namespace std;
    const int N=105;
    int m[N], f[N][N];
    string s;
    
    bool chk(int l, int r, int sz) {
        for (int i=l; i<=r-sz; i++) if (s[i]!=s[i+sz])
            return false;
        return true;
    }
    void init() {
        for (int i=1; i<10; i++) m[i]=1;
        for (int i=10; i<100; i++) m[i]=2;
        m[100]=3;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>s; 
        int n=s.size(); s=" "+s;
        init();
        memset(f, 0x3f3f3f3f, sizeof f);
        for (int i=1; i<=n; i++) f[i][i]=1;
        
        for (int len=2; len<=n; len++)
        for (int i=1; i<=n-len+1; i++) {
            int j=i+len-1;
            for (int k=i; k<j; k++) {
                int sz=k-i+1;      //sz是循环节的大小
                if (len%sz==0 && chk(i,j,sz)) { 
                    f[i][j]=min(f[i][j], f[i][k]+2+m[len/sz]);
                }
            }
            for (int k=i; k<j; k++) {
                f[i][j]=min(f[i][j], f[i][k]+f[k+1][j]);
            }
        }
        cout << f[1][n];
        return 0;
    }
    

    复杂度分析

    • Time\(O(n^3)\)
    • Space\(O(n^2)\)
  • 相关阅读:
    ioctl函数用法小记
    scanf函数用法小记
    printf函数用法小记
    REDIS
    lspci 虚拟机网卡对应关系
    vmware安装ubuntu " Intel VT-x 处于禁用状态"
    win10远程桌面配置
    Win10如何彻底禁用小娜?彻底禁用小娜的方法
    为什么Windows7打开项目的方式是灰的不能修改
    以下suse11.3x64可以安装pycrypto-2.6.1
  • 原文地址:https://www.cnblogs.com/wdt1/p/13673191.html
Copyright © 2011-2022 走看看