Folding

题意:

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

分析:

不是太好想,如果让求最短长度还好,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;
}

 

posted on 2015-10-25 20:37  积跬步、至千里  阅读(187)  评论(0编辑  收藏  举报

导航