您的位置:首页 > 其它

Folding

2015-10-25 20:37 239 查看
题意:

给定一个串,求能化成的最短循环节串(把重复字符串转化成循环节形式)

分析:

不是太好想,如果让求最短长度还好,dp[i][j],表示区间[i,j]化成的最小长度,dp[i][j]=min(dp[i][k]+dp[k+1][j]),即可但现在要求这个串不知怎么做,想着串能不能跟着转移啊,就用 str[l][r]表示区间[l,r]能化成的最短串,接着就是想怎么跟着转移了,当枚举k时,求出使得最短的k,str[l][r]=str[l][k]+str[k+1][r],再判断是否能再次循环。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
char s[110];
string str[110][110];
int dp[110][110];
int len(int l,int r){
for(int i=1;i<=(r-l+1)/2;++i){
if((r-l+1)%i)continue;
int f=1;
for(int j=l;j+i<=r;++j)
{
if(s[j]!=s[j+i]){
f=0;
break;
}
}
if(f)return i;
}
return 0;
}
int dfs(int l,int r){
if(dp[l][r]!=-1)return dp[l][r];
if(l==r){
dp[l][r]=1;
str[l][r]=s[l];
return 1;
}
int minv=INF,pos;
for(int i=l;i<r;++i){
int tmp=dfs(l,i)+dfs(i+1,r);
if(tmp<minv){
pos=i;
minv=tmp;
}
}
str[l][r]=str[l][pos]+str[pos+1][r];
int c=len(l,r);
if(c){
int t=(r-l+1)/c;
string s1="";
while(t){
s1+=('0'+t%10);
t/=10;
}
reverse(s1.begin(),s1.end());
s1+="("+str[l][l+c-1]+")";
if(s1.size()<minv)
{
minv=s1.size();
str[l][r]=s1;
}
}
return dp[l][r]=minv;
}
int main()
{
while(~scanf("%s",s)){
memset(dp,-1,sizeof(dp));
int n=strlen(s);
dfs(0,n-1);
cout<<str[0][n-1]<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: