AcWing 319/poj 2176 folding(区间dp,kmp,最小循环节)

传送门
题目大意:可以把给定的字符串进行若干次折叠.即把ABABABAB这种有循环节的字符串折叠成为4(AB).需要注意的是,这个折叠是可以嵌套的,例如下面这个字符串:
ABABABXYZXYZXYZXYZNASANASAABABABXYZXYZXYZXYZNASANASA
第一次折叠后:
2(ABABABXYZXYZXYZXYZNASANASA)
第二次折叠后:
2(3(AB)4(XYZ)2(NASA))
这是这题的唯一坑点.
我的思路很暴力,每次检测[l,r]看是否能够折叠.这个过程用一次kmp就可以解决.最小循环节存在的条件:字符串的长度设为n 若next[n] && n%(n-next[n]) == 0.循环节长度==n-next[n].网上有不少关于这方面的讲解.就不进行证明了.
代码

#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>

using namespace std;
const int N = 2e5+10;
const int INF = 0x3f3f3f3f;

inline void read(int &a){
    
    
    int x = 0,f=1;char ch = getchar();
    while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){
    
    x=x*10+ch-'0';ch=getchar();}
    a = x*f;
}
int n,dp[110][110],nxt[110];
string dps[110][110];

void getnxt(string s){
    
    
    int n = s.size(),i=2,j=0;
    s = ' ' + s;
    mem(nxt,0);
    for(;i<=n;++i){
    
    
        while(j && s[i] != s[j+1]) j = nxt[j];
        if(s[i] == s[j+1]) j++;
        nxt[i] = j;
    }
}
string s;
string dfs(int l,int r){
    
    
    string str = "";
    if(dp[l][r] != INF) return dps[l][r];
    if(l == r){
    
    
        dp[l][r] = 1;
        str += s[l];
        return dps[l][r] = str;
    }
    int res = 0;
    string tmp="";
    fir(i,l,r) tmp += s[i];
    int siz = tmp.size();
    getnxt(tmp);
    int replen = siz-nxt[siz];
    if(nxt[siz] && siz % replen == 0){
    
    
        res = 2;
        int len = siz/(replen);
        while(len){
    
    
            res++;
            str += char((len%10)+'0');
            len/=10;
        }
        reverse(ALL(str));
        str += '(';
        str += dfs(l,l+replen-1);
        res += dp[l][l+replen-1];
        str += ')';
    }
    else res = INF;
    fir(i,0,r-l-1){
    
    
        string s1 = dfs(l,l+i),s2 = dfs(l+i+1,r);
        if(res > dp[l][l+i]+dp[l+i+1][r]){
    
    
            str = s1+s2;
        }
        res = min(res,dp[l][l+i]+dp[l+i+1][r]);
    }
    dp[l][r] = res;
    return dps[l][r] = str;
}
int main(){
    
    
    cin >> s;
    n = s.size();
    s = ' ' + s;
    mem(dp,INF);
    cout << dfs(1,n);
    
    return 0;
}    

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/108022192