OPENJUDGE NOI 8471 切割回文
来源:互联网 发布:java 开源打码插件 编辑:程序博客网 时间:2024/06/10 06:31
OPENJUDGE NOI 8471 切割回文
总时间限制: 1000ms 内存限制: 65536kB
描述
阿福最近对回文串产生了非常浓厚的兴趣。
如果一个字符串从左往右看和从右往左看完全相同的话,那么就认为这个串是一个回文串。例如,“abcaacba”是一个回文串,“abcaaba”则不是一个回文串。
阿福现在强迫症发作,看到什么字符串都想要把它变成回文的。阿福可以通过切割字符串,使得切割完之后得到的子串都是回文的。
现在阿福想知道他最少切割多少次就可以达到目的。例如,对于字符串“abaacca”,最少切割一次,就可以得到“aba”和“acca”这两个回文子串。
输入
输入的第一行是一个整数 T (T <= 20) ,表示一共有 T 组数据。
接下来的 T 行,每一行都包含了一个长度不超过的 1000 的字符串,且字符串只包含了小写字母。
输出
对于每组数据,输出一行。该行包含一个整数,表示阿福最少切割的次数,使得切割完得到的子串都是回文的。
【题目分析】
第一次用Markdown写博客,感觉好赞。
收一收激动的心情,我来写题解,首先看到这道题就是很简单的背包类型的动态规划,显然是要不留缝隙地填满的。很容易想到动态规划,如果不预处理,是N^3的,然后加一个预处理复杂度就是N^2了,详见代码1.(其实这个代码是从隔壁抄来的@yhx相信他不会介意的)30ms
#include<cstdio>#include<cstring>bool b[1010][1010];int dp[1010];char s[1010];int min(int x,int y){ if (x<y) return x; return y; } int main(){ int i,j,k,l,m,n,p,q,x,y,z,T,mid; scanf("%d",&T); while (T--) { memset(b,0,sizeof(b)); memset(dp,0x42,sizeof(dp)); scanf("%s",s+1); l=strlen(s+1); for (k=1;k<=l;k++) for (i=1;i+k-1<=l;i++) { j=i+k-1; if (k<=2) { if (s[i]==s[j]) b[i][j]=1; } else { if (b[i+1][j-1]&&s[i]==s[j]) b[i][j]=1; } } dp[0]=0; for (i=1;i<=l;i++) for (j=0;j<=i;j++) if (b[j][i]) dp[i]=min(dp[i],dp[j-1]+1); printf("%d\n",dp[l]-1); }}
然后我脑洞大开,可以把预处理降到N的级别,显然对总体的时间复杂度并没有什么卵用。以下是优化过的代码二。然而事实证明,比上一种方法快了两倍,#(滑稽)只有10ms。
#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int r[2010],dp[2010];char s[2010],ch[2010];inline int min(int a,int b){return a>b?b:a;}inline bool pd(int l,int e){ if ((r[l+e]*2-1)/2>=e-l+1) return true; else return false;}int main(){ int tt; scanf("%d",&tt); while (tt--) { memset(r,0,sizeof r); memset(dp,0x3f,sizeof dp); memset(r,0,sizeof r); dp[0]=0; scanf("%s",ch+1); int l=strlen(ch+1); s[1]='#';s[2*l+2]='#';//处理一下回文串 for (int i=1;i<=l;++i) { s[i*2]=ch[i]; s[i*2|1]='#'; } int id=0,mx=0;//高逼格manacher r[0]=1; for (int i=1;i<=2*l+1;++i){ if (mx>i) r[i]=min(r[2*id-i],mx-i); else r[i]=1; while (s[i-r[i]]==s[i+r[i]]) r[i]++; if (i+r[i]>mx) mx=i+r[i],id=i; } for (int i=1;i<=l;++i)//动态规划 for (int j=1;j<=i;++j) if (pd(j,i)) dp[i]=min(dp[i],dp[j-1]+1); printf("%d\n",dp[l]-1); }}
0 2
- OPENJUDGE NOI 8471 切割回文
- 【openjudge】切割回文
- openjudge 切割回文
- Openjudge切割回文(pku t1)
- [OpenJudge-NOI]词典 stl
- [OpenJudge-NOI]Set stl
- [OpenJudge-NOI]List stl
- NOI OpenJudge 1159 Maze
- NOI OpenJudge 1805 碎纸机
- NOI OpenJudge 726 ROADS
- noi openjudge 数字组合
- OpenJudge-Noi 1996 登山
- noi.openjudge 11207 机器翻译
- noi.openjudge 1909 直方图
- NOI openjudge 1792.迷宫
- openjudge noi 9278 旅行
- openjudge noi 1805 碎纸机
- Openjudge NOI题库1.7编程基础之字符串 34:回文子串
- socket中的虚拟端口号port
- 网络编程中常见的5种I/O模型
- 反转算法
- ACM题集总结大全
- 设计模式总结:概念、原则、23种模式分析
- OPENJUDGE NOI 8471 切割回文
- mac os charles 抓包http/https的简单使用介绍(附3.10.1mac破解版下载链接)
- 爬虫系列1:python简易爬虫分析
- linux字符设备驱动
- CentOS-6.5-x86 安装 jdk-7u79-linux-i586.rpm
- Jaccard相似系数和皮尔逊相关系数
- linux安装tomcat
- 学生信息管理系统----错误集锦(二)
- hdu5579 2015区域赛上海赛区G.Game of Arrays