luogu4302字符串折叠题解--区间DP

题目链接

https://www.luogu.org/problemnew/show/P4302

分析

很明显一道区间DP题,对于区间\([l,r]\)的字符串,如果它的字串是最优折叠的,那么它的最优结果要么是所有分割出的字串最优结果之和,要么是在断点处恰好有这个区间的周期串可以进行折叠,折叠后产生的结果

状态转移

 for(ri len=2;len<=n;len++){//枚举长度,套路
        for(l=1;l<=n-len+1;l++){
            r=l+len-1;
            for(ri k=l;k<r;k++){//枚举断点
                f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);//分割出的子串结果之和
                x=check(l,k,r);////[k+1,rr]能否由[l,k]的串循环而成
                if(x!=-1){//如果能
                    f[l][r]=min(f[l][r],f[l][k]+2+x);//显而易见的转移
                }
            }
        }
    }

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
#define ll long long
#define ri register int
using std::min;
using std::max;
using std::swap;
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c==‘-‘;
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;return ;
}
const int maxn=205;
int n,m,f[maxn][maxn];
char s[maxn];
inline int check(int l,int r,int rr){//[r+1,rr]能否由[l,r]的串循环而成
    int x,st,len1=r-l+1,len2=rr-l+1;
    if(len2%len1)return -1;
    x=len2/len1;
    for(ri i=1;i<=x;i++){
        st=l+(i-1)*len1;
        for(ri j=0;j<len1;j++) if(s[l+j]!=s[st+j]) return -1;
    }
    int cnt=0;
    while(x){x/=10;cnt++;}
    return cnt;
}
int main(){
    int l,r,x;
    scanf("%s",s+1); n=strlen(s+1);
    for(ri i=0;i<=n;i++)
        for(ri j=i;j<=n;j++) f[i][j]=j-i+1;
    for(ri len=2;len<=n;len++){
        for(l=1;l<=n-len+1;l++){
            r=l+len-1;
            for(ri k=l;k<r;k++){//枚举断点
                f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);//分割出的子串结果之和
                x=check(l,k,r);//能否成为周期串
                if(x!=-1){
                    f[l][r]=min(f[l][r],f[l][k]+2+x);
                }
            }
        }
    }
    printf("%d\n",f[1][n]);
    return 0;
}

原文地址:https://www.cnblogs.com/Rye-Catcher/p/9648309.html

时间: 2024-10-09 08:07:17

luogu4302字符串折叠题解--区间DP的相关文章

BZOJ 1090 字符串折叠(区间DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1090 题意:字符串AAAAAAAAAABABABCCD的最短折叠为9(A)3(AB)CCD,注意数字的长度和圆括号都算最后长度.求一种折叠方式使得总长度最小. 思路:f[L][R]=min(R-L+1,f[L][i]+f[i+1][R]),另外若[L,R]能由[i+1,R]重复若干次,则也可用折叠后的长度更新f[L][R]. char s[N]; int f[N][N],n; int

bzoj 1090 [SCOI2003]字符串折叠(区间DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1090 [题意] 给定一个字符串,问将字符串折叠后的最小长度. [思路] 设f[i][j]表示将区间ij折叠后的最小长度,则有转移式: f[i][j]=min{ j-i+1,f[i][k]+f[k+1][j],f[i][i+x-1]+2+digit((j-i+1)/x) } 第一项代表不折叠,第二项代表当前不折叠,第三项代表以x长度折叠ij区间,条件是满足ij区间以x为循环节. [代码

[SCOI2003]字符串折叠(区间dp)

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的最短折叠为

hdu 4632 子字符串统计的区间dp

题意:查找这样的子回文字符串(未必连续,但是有从左向右的顺序)个数. 简单的区间dp,哎,以为很神奇的东西,其实也是dp,只是参数改为区间,没做过此类型的题,想不到用dp,以后就 知道了,若已经知道[0,i],推[0,i+1], 显然还要从i+1 处往回找,dp方程也简单: dp[j][i]=(dp[j+1][i]+dp[j][i-1]+10007-dp[j+1][i-1])%10007; 减去中间一段重复的 if(s[i]==s[j])dp[j][i]=(dp[j][i]+dp[j+1][i-

Blocks题解(区间dp)

Blocks题解 区间dp 阅读体验...https://zybuluo.com/Junlier/note/1289712 很好的一道区间dp的题目(别问我怎么想到的) dp状态 其实这个题最难的地方是这道题目的状态怎么设 首先既然是区间dp,那肯定最先想到的状态是 $dp[i][j]$表示消掉区间$[i,j]$上所有的块的最大分数 突然发现这个状态会受区间外和$i$或$j$颜色相同的块的影响 并且转移也并不好转移=_= 所以我们考虑换一种状态... 既然说会受到外面的块的影响?那考虑一种方法来

BZOJ 1090 字符串折叠(Hash + DP)

题目链接 字符串折叠 区间DP.f[l][r]为字符串在区间l到r的最小值 正常情况下 f[l][r] = min(f[l][r], f[l][l + k - 1] + f[l + k][r]); 当l到r以k为周期时 f[l][r] = min(f[l][r], 2 + sz(k) + f[l][l + (r - l + 1) / k - 1]); 判重的时候为了方便我用了哈希……当然其他方法应该也是可以的~ #include <bits/stdc++.h> using namespace

POJ2955 Brackets 题解 区间DP

题目链接:http://poj.org/problem?id=2955[题目描述]<规则的括号序列>我们定义一个字符串序列为“规则的括号序列”当且仅当它满足如下条件:1.空字符串是规则的括号序列:2.如果字符串 s 是一个规则的括号序列,那么 (s) 和 [s] 也是规则的括号序列:3.如果字符串 a 和 b 都是规则的括号序列,那么 ab 也是规则的括号序列:4.除此之外的字符串都不能称为规则的括号序列.举个例子,下面的这些字符串都是规则的括号序列: (), [], (()), ()[],

HDU4632 Palindrome subsequence 题解 区间DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632[题目描述]<回文子串数量>给你一个长度为N(N≤1000)的字符串,你输出它所有的回文子串的数量(对10007取模).只要从字符串 s 中顺序地取出一些字符(不要求连续,可以是 s 本身,不能是空串),不改变他们的顺序的情况下,这个子串是一个回文串,那么他就是一个 s 的回文子串.[输入格式]首先是一个数T(T≤50),表示测试用例的数量.接下来T行,每行包含一个字符串.[输出格式]对于每一

POJ 1651 Multiplication Puzzle 题解 区间DP

题目链接:http://poj.org/problem?id=1651[题目描述]<乘法谜题>乘法谜题源自这样一个背景,我们有一行 n 张牌,平铺在桌面上,每张牌的牌面上都标有一个正整数.玩家的初始得分是 0,他接下来要进行 n-2 次操作,每次操作他都需要从桌面上取出一张牌,然后他的得分会加上他取出的这张牌与取出的这张牌的左边的牌以及取出的这张牌的右边的牌的乘积.在第 n-2 次操作结束后,桌面上将会只剩下两张牌.你的目的是帮助玩家决定取牌的顺序,使得玩家的最终得分最小.举个例子,如果一开始