Codeforces Gym 100002 Problem F "Folding" 区间DP

代码优化:利用区间DP解决序列折叠问题
本文深入探讨了使用区间动态规划(DP)技术解决序列折叠问题的方法,旨在通过最小化字符数量实现序列的高效压缩。通过实例解析,展示了如何在给定序列中识别重复子序列并应用区间DP算法进行最优压缩。此技术对于处理大量数据和优化存储具有重要意义。

Problem F "Folding"

Time Limit: 1 Sec  

Memory Limit: 256 MB

题目连接

http://codeforces.com/gym/100002

Description

Bill is trying to compactly represent sequences of capital alphabetic characters from 'A' to 'Z' by folding repeating subsequences inside them. For example, one way to represent a sequence AAAAAAAAAABABABCCD is 10(A)2(BA)B2(C)D. He formally defines folded sequences of characters along with the unfolding transformation for them in the following way:

  • 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.

According to this definition it is easy to unfold any given folded sequence. However, Bill is much more interested in the reverse transformation. He wants to fold the given sequence in such a way that the resulting folded sequence contains the least possible number of characters.

Input

The input file contains a single line of characters from 'A' to 'Z' with at least 1 and at most 100 characters.

Output

Write to the output file a single line that contains the shortest possible folded sequence that unfolds to the sequence that is given in the input file. If there are many such sequences then write any one of them.

Sample Input

AAAAAAAAAABABABCCD

Sample Output

9(A)3(AB)CCD

HINT

 

题意

就是相同的可以被压缩,问你最少压缩成什么样子(注意,括号和数字也算长度

题解:

区间DP,维护区间DP的时候,同时维护一下这个区间的字符串是什么样子的就好了

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 110000
#define mod 10007
#define eps 1e-9
#define pi 3.1415926
int Num;
//const int inf=0x7fffffff;   //§ß§é§à§é¨f§³
const ll Inf=0x3f3f3f3f3f3f3f3fll;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//**************************************************************************************

string s[110][110];
int n;
int dp[110][110];
int vis[110][110];
char S[110];
int FF(int x)
{
    int add=0;
    while(x)
    {
        add++;
        x/=10;
    }
    return add;
}
string F(int x)
{
    string ss;
    while(x)
    {
        ss+=(char)(x%10+'0');
        x/=10;
    }
    reverse(ss.begin(),ss.end());
    return ss;
}
int solve(int l,int r)
{
    if(vis[l][r])return dp[l][r];
    vis[l][r]=1;
    for(int i=l;i<r;i++)
    {
        if(dp[l][r]>solve(l,i)+solve(i+1,r))
        {
            dp[l][r]=dp[l][i]+dp[i+1][r];
            s[l][r]=s[l][i]+s[i+1][r];
        }
    }
    for(int i=1;i<r-l+1;i++)
    {
        if((r-l+1)%(i)!=0)
            continue;
        int add = 0;
        for(int k=0;;k++)
        {
            if((k+1)*i>r-l+1)
                break;
            for(int j=0;j<i;j++)
            {
                if(S[l+k*i+j]!=S[l+j])
                    break;
                if(j==i-1)
                    add+=1;
            }
        }

        if(add==(r-l+1)/i)
        {
            int point=solve(l,l+i-1)+2+FF(add);
            if(dp[l][r]>point)
            {
                dp[l][r]=point;
                s[l][r]="";
                s[l][r]+=F(add)+'(';
                s[l][r]+=s[l][(1)*i-1+l];
                s[l][r]+=')';
            }
        }
    }
    return dp[l][r];
}
int main()
{
    freopen("folding.in","r",stdin);
    freopen("folding.out","w",stdout);
    scanf("%s",S+1);
    n = strlen(S+1);
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            dp[i][j]=j-i+1;
            for(int k=0;k<j-i+1;k++)
            {
                s[i][j]+=S[i+k];
            }
        }
    }
    solve(1,n);
    cout<<s[1][n]<<endl;
    return 0;
}

 

Codeforces Gym 101630 是一场编程竞赛,通常包含多个算法挑战问题。这些问题往往涉及数据结构算法设计、数学建模等多个方面,旨在测试参赛者的编程能力和解决问题的能力。 以下是一些可能出现在 Codeforces Gym 101630 中的题目类型及解决方案概述: ### 题目类型 1. **动态规划(DP)** 动态规划是编程竞赛中常见的题型之一。问题通常要求找到某种最优解,例如最小路径和、最长递增子序列等。解决这类问题的关键在于状态定义和转移方程的设计[^1]。 2. **图论** 图论问题包括最短路径、最小生成树、网络流等。例如,Dijkstra 算法用于求解单源最短路径问题,而 Kruskal 或 Prim 算法则常用于最小生成树问题[^1]。 3. **字符串处理** 字符串问题可能涉及模式匹配、后缀数组、自动机等高级技巧。KMP 算法和 Trie 树是解决此类问题的常用工具[^1]。 4. **数论组合数学** 这类问题通常需要对质数、模运算、排列组合等有深入的理解。例如,快速幂算法可以用来高效计算大数的模幂运算[^1]。 5. **几何** 几何问题可能涉及点、线、多边形的计算,如判断点是否在多边形内部、计算两个圆的交点等。向量运算和坐标变换是解决几何问题的基础[^1]。 ### 解决方案示例 #### 示例问题:动态规划 - 最长递增子序列 ```python def longest_increasing_subsequence(nums): if not nums: return 0 dp = [1] * len(nums) for i in range(len(nums)): for j in range(i): if nums[i] > nums[j]: dp[i] = max(dp[i], dp[j] + 1) return max(dp) # 示例输入 nums = [10, 9, 2, 5, 3, 7, 101, 18] print(longest_increasing_subsequence(nums)) # 输出: 4 ``` #### 示例问题:图论 - Dijkstra 算法 ```python import heapq def dijkstra(graph, start): distances = {node: float('infinity') for node in graph} distances[start] = 0 priority_queue = [(0, start)] while priority_queue: current_distance, current_node = heapq.heappop(priority_queue) if current_distance > distances[current_node]: continue for neighbor, weight in graph[current_node].items(): distance = current_distance + weight if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(priority_queue, (distance, neighbor)) return distances # 示例输入 graph = { 'A': {'B': 1, 'C': 4}, 'B': {'A': 1, 'C': 2, 'D': 5}, 'C': {'A': 4, 'B': 2, 'D': 1}, 'D': {'B': 5, 'C': 1} } start = 'A' print(dijkstra(graph, start)) # 输出: {'A': 0, 'B': 1, 'C': 3, 'D': 4} ``` #### 示例问题:字符串处理 - KMP 算法 ```python def kmp_failure_function(pattern): m = len(pattern) lps = [0] * m length = 0 # length of the previous longest prefix suffix i = 1 while i < m: if pattern[i] == pattern[length]: length += 1 lps[i] = length i += 1 else: if length != 0: length = lps[length - 1] else: lps[i] = 0 i += 1 return lps def kmp_search(text, pattern): n = len(text) m = len(pattern) lps = kmp_failure_function(pattern) i = 0 # index for text j = 0 # index for pattern while i < n: if pattern[j] == text[i]: i += 1 j += 1 if j == m: print("Pattern found at index", i - j) j = lps[j - 1] elif i < n and pattern[j] != text[i]: if j != 0: j = lps[j - 1] else: i += 1 # 示例输入 text = "ABABDABACDABABCABAB" pattern = "ABABCABAB" kmp_search(text, pattern) # 输出: Pattern found at index 10 ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值