luogu P4302 [SCOI2003]字符串折叠

题目描述

折叠的定义如下:

一个字符串可以看成它自身的折叠。记作S = S
X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S) = SSSS…S(X个S)。
如果A = A’, B = B’,则AB = A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B) = AAACBB,而2(3(A)C)2(B) = AAACAAACBB
给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。

输入格式

仅一行,即字符串S,长度保证不超过100。

输出格式

仅一行,即最短的折叠长度。


区间动态规划

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=105;
int a[N],n,m[N];
int f[N][N];
inline bool check(int l,int r,int len){
	for(int i=l;i<=r;i++)
	if(a[i]!=a[(i-l)%len+l])return 0;
	return 1;
}
int main(){
	char c;
	while(1){
		c=getchar();
		if(c=='
')break;
		a[++n]=c-'A'+1;
	}
	for(int i=1;i<=9;i++)m[i]=1;
	for(int i=10;i<=99;i++)m[i]=2;
	m[100]=3;
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=n;i++)f[i][i]=1;
	
	for(int len=2;len<=n;len++)
	for(int l=1;l+len-1<=n;l++){
		int r=l+len-1;
		for(int k=l;k<r;k++)
		f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
		for(int k=l;2*k-l+1<=r;k++){
			int op=k-l+1;
			if(len%op!=0)continue;
			if(check(l,r,op))
			f[l][r]=min(f[l][r],f[l][k]+2+m[len/op]);
		}
	}
	cout<<f[1][n]-1<<endl;
}
原文地址:https://www.cnblogs.com/naruto-mzx/p/11656812.html