[ZROI #316] ZYB玩字符串

摘要:
min:sub,f=1;}如果{cout<<res<<endl;break;}}}}返回0;}回顾:最近看了几篇文章后,我觉得我对动态规则有了更好的理解。事实上,动态规则是一种通过定义状态和传递方程将问题划分为多个子问题来解决问题的想法。实现方法是递归还是基于内存的搜索递归,与拆分问题的想法无关。思考问题的心理过程很方便:找到合法字符串的性质,通过定义$dp[l][r]$来拆分问题并根据其属性写出转移方程,发现转移方程更容易以递归形式实现,并通过记忆搜索来解决

Introduction

每次在一开始为空的串$S$的任意位置插入串$p$

给出最终的$S$,求长度最短(相同时字典序最小)的串$p$

Solution:

样例出锅差评啊,让我这种直接看样例选手挂掉50分啊……

所以说不管怎么样都要好好看输入/输出格式,看看有没有多测

非常直观的思路就是$O(len^2)$枚举所有$S$的子串进行判断

暴力的话就是每次选择一个$p$将其删去并继续递归下去

同时对于随机的点可以直接上贪心:每次直接删去第一个$p$

接下来考虑满分算法

首先$O(len^2)$对$p$的枚举无法优化,只能优化判断的过程

发现每个串$p$被分为几段后,中间的每一段都是独立完整的一段

那么一段的合法性取决于其是否能分成几段合法段且剩下的组成当前字符串的前缀

这样将问题拆分后就可以$dp$了,用$dp[l][r]$来表示区间$[l,r]$是否合法,转移如下:

1、$r$属于最外层的串$p$:$dp[l][r]=dp[l][r-1]&s[r]==sub[(r-l) mod len+1]$

2、$r$在完整的段中:$dp[l][r]=dp[l][r-len*k]&dp[r-len*k+1][r]$

这样的转移明显不太容易递推,因此用记忆化搜索处理,复杂度上界为$O(len^4)$

不过这其实是一个很松的上界,首先$p$的长度必须为$len$的约数

同时可以对字符集个数判断(虽然我没写),而且由于是记忆化搜索状态数达不到$O(len^2)$

Tips:$string$在未赋值时长度为0,不能访问$string[i]$来赋值,是越界行为,要先$resize()$!

Code:

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
typedef double db;
const int MAXN=205;
string s,sub,res;
int len,T,dp[MAXN][MAXN],cur;

int solve(int l,int r)
{
    if(l>r) return 1;
    if(~dp[l][r]) return dp[l][r];
    
    for(int mid=r-cur;mid>=l;mid-=cur)
        if(solve(l,mid)&&solve(mid+1,r))
            return dp[l][r]=1;
    if(s[r-1]==sub[(r-l)%cur]) return dp[l][r]=solve(l,r-1);
    return dp[l][r]=0;
}

int main()
{
    cin>>T;
    while(T--)
    {
        bool f=0;cin>>s;len=s.size();
        for(cur=1;cur<=len;cur++)
            if(len%cur==0)
            {
                for(int j=0;j<=len-cur;j++)
                {
                    sub=s.substr(j,cur);
                    memset(dp,-1,sizeof(dp));
                    if(solve(1,len))
                        res=f?min(res,sub):sub,f=1;
                }
                if(f){cout<<res<<endl;break;}
            }
    }
    return 0;
}

Review:

最近看了几篇文章感觉对动规有了更多的理解

动规其实是一种通过状态的定义和转移方程将问题拆成多个子问题来解决的一种思想

实现方式究竟是递推还是记忆化搜索式的递归其实与其拆分问题的思想无关,用方便的即可

比如思考此题的心路历程:

发现合法字符串的性质,通过定义$dp[l][r]$根据性质将问题拆分写出转移方程

发现转移方程用递归的形式更容易实现,用记忆化搜索解决

免责声明:文章转载自《[ZROI #316] ZYB玩字符串》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[P2664] 树上游戏[Codeforces #172] Tutorial下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

iOS开发库的族谱介绍 狼人:

Foundation/Core Foundation/Carbon/Cocoa/Cocoa Touch/Toll Free Bridging光看看这tm些名字就jb够晕了,你是不是也看着这些东西恶心?你是不是也发现在你开发同样一个功能的时候,从a库也可以到达,从b库也可以到达?虽然都能抓住老鼠,可是到底哪只猫是串儿?哪只猫是纯种的波斯猫? 本文就是对这些库族...

OpenCV视频目标跟踪示例教程(Meanshift)

使用Opencv中的Camshift进行视频中目标跟踪是一个不错的选择,这方面的示例很多,但是大多代码不全,或者代码存在问题,不能正常使用,这里,对很多文章进行整理后,贴出了正确可以使用的代码。 首先下载OpenCV, http://sourceforge.net/projects/opencvlibrary/ 安装Opencv ,他是exe,可以直接安装...

jquery两级边动完整例子

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title> New Document </title><MET...

发布一个开源的c++网络事件库 知然 博客园

发布一个开源的c++网络事件库 - 知然 - 博客园 发布一个开源的c++网络事件库 Chaos是一个基于Linux平台, reactor模式的网络事件库,目前仅支持TCP传输协议,仅在x86_64下编译,并遵循3-clause BSD开源协议.在使用上,可以说它很像boost asio,可能是由于我对boost asio的接口设计很有爱吧,而且对于bo...

文档中心 FetchURL Sina App Engine

文档中心 - FetchURL - Sina App Engine FetchURL 服务概要 应用场景 使用指南 抓取页面 发起POST请求 错误码参考 服务限制与配额 服务限制 分钟配额 常见问题 收起 服务概要 应用场景 使用指南 服务限制与配额 常见问题...

很奇怪,给人家的server部署munin很方便(包括centos或者ubunt…

很奇怪,给人家的server部署munin很方便(包括centos或者ubunt… | Tin's Blog 很奇怪,给人家的server部署munin很方便(包括centos或者ubunt… Written by tin at 6:06 am on 2009/12/31 很奇怪,给人家的server部署munin很方便(包括centos或者ubun...