列表

详情


NC20252. [SCOI2007]压缩

描述

给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。
压缩后的字符串除了小 写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没 有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 
bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程
   
另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。

输入描述

输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。

输出描述

输出仅一行,即压缩后字符串的最短长度。

示例1

输入:

bcdcdcdcdxcdcdcdcd

输出:

12

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 3ms, 内存消耗: 380K, 提交时间: 2020-07-15 10:41:37

#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
int dp[110][110][2];
string s;
bool check(int i,int j){
	if((j-i+1)%2!=0) return false;
	int mid=i+j>>1;
	j=mid+1;
	while(i<=mid){
		if(s[i]!=s[j]) return false;
		i++;j++;
	}
	return true;
}
int main(){
	cin>>s;
	int sz=s.size();
	s='#'+s;
	for(int len=1;len<=sz;len++){
		for(int i=1;i+len-1<=sz;i++){
			int j=i+len-1;
			dp[i][j][0]=dp[i][j][1]=len;
			for(int k=i;k<j;k++) 
				dp[i][j][0]=min(dp[i][j][0],dp[i][k][0]+j-k);
			if(check(i,j)) dp[i][j][0]=min(dp[i][j][0],dp[i][(i+j)/2][0]+1);
			for(int k=i;k<j;k++)
				dp[i][j][1]=min(dp[i][j][1],min(dp[i][k][0],dp[i][k][1])+1+min(dp[k+1][j][0],dp[k+1][j][1]));
		}
	}
	cout<<min(dp[1][sz][0],dp[1][sz][1])<<endl;
}

C++(clang++11) 解法, 执行用时: 13ms, 内存消耗: 484K, 提交时间: 2021-02-14 15:07:39

#include<bits/stdc++.h>
using namespace std;
char s[100];
int n;
int dp[55][55][2];
bool check(int l,int r)
{
	if((r-l+1)&1)
	return false;
	for(int i=l;i<=(l+r)/2;i++)
	if(s[i]!=s[i+(r-l+1)/2])
	return false;
	return true;
}
int dfs(int l,int r,bool cur)
{
	if(~dp[l][r][cur])
	return dp[l][r][cur];
	if(l==r)
	return dp[l][r][cur]=1;
	int tans=0x3f3f3f3f;
	if(!cur)
	for(int i=l;i<r;i++)
	tans=min(tans,dfs(l,i,0)+dfs(i+1,r,0)+1);
	for(int i=l;i<r;i++)
	tans=min(tans,dfs(l,i,cur)+r-i);
	if(check(l,r))
	tans=min(tans,dfs(l,(l+r)/2,1)+1);
	return dp[l][r][cur]=tans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	scanf("%s",s+1);
	n=strlen(s+1);
	printf("%d",dfs(1,n,0));
	return 0;
}

pypy3(pypy3.6.1) 解法, 执行用时: 95ms, 内存消耗: 30504K, 提交时间: 2020-08-02 20:37:11

#!/usr/bin/env python3
#
# [SCOI2007] 压缩
#
import sys, os

s = input().strip()
n = len(s)

def check(i, j):
	if j - i <= 0: return False
	for k in range(j - i):
		if s[i + k] != s[j + k]: return False
	return True

dp = [[None] * (n + 1) for _ in range(n + 1)]

for l in range(1, n + 1):
	for i in range(0, n - l + 1):
		j = i + l
		dp[i][j] = [l, l]
		for k in range(i + 1, j):
			dp[i][j][0] = min(dp[i][j][0], dp[i][k][0] + j - k)
			dp[i][j][1] = min(dp[i][j][1], min(dp[i][k]) + min(dp[k][j]) + 1)
		if l % 2 == 0 and check(i, i + l // 2):
			dp[i][j][0] = min(dp[i][j][0], dp[i][(i + j) >> 1][0] + 1)

print(min(dp[0][-1]))

上一题