hdu 5340(manacher+枚举)
来源:互联网 发布:淘宝上的mre单兵口粮 编辑:程序博客网 时间:2024/05/14 06:07
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5340
解题思路:首先用manacher处理每个字符,接下来就是要枚举了。
首先是我想到的dp,dp[i][j]表示第i个字符结尾的第j个回文串是否存在。
dp[i+k-1][j] = 1 if(dp[i-k+1][j-1] == 1),k当前表示回文串的半径长度
最后只需要判断dp[len][3]即可。
但很可惜超时了。
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn = 20005;int p[maxn<<1],dp[maxn<<1][4];char str[maxn],c[maxn];void manacher(int len){int id = 0;p[0] = 1;for(int i = 1; i <= 2 * len; i++){if(id + p[id] > i) p[i] = min(p[2*id-i],id + p[id] - i);else p[i] = 1;while(i-p[i]>=0 && i+p[i]<=2*len && c[i-p[i]]==c[i+p[i]]) p[i]++;if(i+p[i] > id+p[id])id = i;}}int main(){int t;scanf("%d",&t);while(t--){memset(dp,0,sizeof(dp));scanf("%s",str+1);int len = strlen(str+1);c[0] = '#';for(int i = 1; i <= len; i++){c[2*i-1] = str[i];c[2*i] = '#';}manacher(len);dp[0][0] = 1;for(int i = 1; i < 2 * len; i++)for(int j = 1 + (i % 2 == 0); j <= p[i]; j++)for(int k = 1; k <= 3; k++){if(dp[i - j + 1][k-1])dp[i + j - 1][k] = 1;}if(dp[2*len][3])printf("Yes\n");else printf("No\n");}return 0;}
其实这里可以枚举第一个串和第三个串的末尾和起始位置,这样就只需要判断中间位置的串是否是回文即可。
#include <cstdio>#include <algorithm>#define MAXN 20010using namespace std;int n;char d[MAXN];///原始字符串char st[MAXN*2];///经过manacher处理之后的字符串int p[MAXN*2];///保存回文串半径,ps每个回文串长度一定为奇数int ll[MAXN*2];///第一个回文串可能的所有半径int rr[MAXN*2];///第三个回文串可能的所有半径void manacher(){ int i; st[0]='$'; st[1]='#'; for(i=1;d[i]!='\0';++i){ st[i*2]=d[i]; st[i*2+1]='#'; } st[i*2]='\0'; n=i*2-1; int MaxId=0,id; for(int i=1;i<=n;i++) { if(MaxId>i) p[i]=min(p[2*id-i],MaxId-i); else p[i]=1; while(st[i+p[i]]==st[i-p[i]]) p[i]++; if(p[i]+i>MaxId){ id=i; MaxId=p[i]+i; } }}int main(){ int res; scanf("%d",&res); while(res--){ scanf("%s",&d[1]); manacher(); int l=0,r=0; for(int i=1;i<=n;i++){ if(p[i]==i&&i!=1)///p[i]==i保证p[i]可以作为第一个回文串的半径,加入ll数组,i!=1保证第一个回文串不为空 ll[l++]=p[i]; if(p[i]+i-1==n&&i!=n)///与上面类似 rr[r++]=p[i]; } int i,j; for(i=l-1;i>=0;--i){ for(j=0;j<=r-1;++j){///枚举第一个回文串和第三个回文串 int tl=2*ll[i];///第二个字符串的开始位置 int tr=n+1-2*rr[j];///第二个字符串的结束位置 int tmp=(tl+tr)/2;///第二个字符串的中间位置,ps:这三个字符串都为奇数,可以自己想想 if(tl>tr) continue; if(p[tmp]==1) continue;///第二个字符串为"#",也即是在原串中为空 if(p[tmp]*2-1>=tr-tl+1)///以tmp为中点的回文串的长度大于等于第二个字符串的长度,符合题意跳出循环 break; } if(j<=r-1) break; } if(i>=0) printf("Yes\n"); else printf("No\n"); } return 0;}
0 0
- hdu 5340(manacher+枚举)
- HDU 5340 Three Palindromes( 折半枚举+Manacher+记录区间 )
- hdu 3613 Best Reward ( manacher+枚举)
- hdu 5340 manacher
- hdu 5340 (manacher)
- HDU 5371 Hotaru's problem(manacher + 枚举啊)
- hdu 5371 Hotaru's problem (Manacher算法+枚举)
- hdu 5340 Three Palindromes 【Manacher】
- UVAlive 4975 Manacher+枚举
- hdu 5340 Three Palindromes(manacher)
- HDU 5340 Three Palindromes(Manacher乱搞)
- HDU 5340-Three Palindromes(Manacher算法)
- hdu-5340 Three Palindromes(Manacher 算法)
- HDU 5340 Three Palindromes (manacher算法)
- HDU 5340 Three Palindromes 暴力+Manacher
- Manacher(枚举位置)+uva11888
- hdu 5340 Manachers + 枚举
- hdu 3068 Manacher
- 分析比较多表查询中的IN与JOIN
- JS绑定事件的三种方式
- PHP用代码实现文件下载
- 数据结构实验之栈七:出栈序列判定
- Cscope
- hdu 5340(manacher+枚举)
- js 将json字符串转换为json对象的方法解析
- android studio 自定义gradle变量
- Java正则表达式整理的工具类
- 枚举类的定义与枚举内容的取出
- javascript面向对象学习笔记(二)——创建对象
- 团体程序设计天梯赛 决赛 L2 列车调度
- 死锁产生的原因和解锁的方法
- hdu2586