首页 技术 正文
技术 2022年11月18日
0 收藏 728 点赞 4,982 浏览 2468 个字

Three Palindromes

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1948    Accepted Submission(s): 687

Problem DescriptionCan we divided a given string S into three nonempty palindromes? InputFirst line contains a single integer T≤20 which denotes the number of test cases.

For each test case , there is an single line contains a string S which only consist of lowercase English letters.1≤|s|≤20000 OutputFor each case, output the “Yes” or “No” in a single line.  Sample Input2abcabaadada  Sample OutputYesNo

题意:给出一个字符串,问能否将字符串分为三段,并且每一段的是回文串。

思路:这题要用到manacher算法,不知道的可以看一下这篇博客:https://blog.csdn.net/dyx404514/article/details/42061017。

首先用manacher求出以每个点为中点的回文串的半径,然后,我们可以知道,要将字符串分为三段,那第一段一定包含第一个字符,第三段一定包含最后一个字符。然后判断第一个回文串和第三个之间剩下的字符是否构成回文串就行了。

所以,我们找到用manacher算法求出的所有回文串中,包含了第一个字符和和最后一个字符的有那些,然后两两配对,看看是否存在某一对,他们不重合,且之间剩下的字符也是回文串。

具体操作看代码:

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#define eps 1e-7
#define ll long long
#define inf 0x3f3f3f3f
#define pi 3.141592653589793238462643383279
using namespace std;
const int maxn = ;
char a[maxn],s_new[maxn<<];
int s_len[maxn<<]; int Init() //manacher算法初始化(模板)
{
int len = strlen(a);
s_new[] = '@';
int j = ;
for(int i=; i<len; ++i) //在每个字符左右插入'#'
{
s_new[j++] = '#';
s_new[j++] = a[i];
}
s_new[j++] = '#';
s_new[j] = '\0';
return j;
} void manacher(int len) //计算以每个点为中心的回文串的半径(模板)
{
int high = ,flag = ;
for(int i=; i<len; ++i)
{
if(i < high)
s_len[i] = min(high-i+ , s_len[*flag-i]);
else
s_len[i] = ; while(s_new[i + s_len[i]] == s_new[i - s_len[i]])
s_len[i]++; if(i + s_len[i] - > high)
{
high = i+ s_len[i] -;
flag = i;
}
}
return;
} bool judge(int len) //判断是否可以分为3个回文串
{
int visit1[maxn<<], visit2[maxn<<], cnt1 = , cnt2 = ;
     //visit1用来存储所有包含第一个字符的字符串的中点下标
//visit2用来存储包含最后一个字符串的中点下标 for(int i=; i<len; ++i) //遍历一遍,找到存入visit数组中
{//因为以 i 为中点的回文串的长度是s_len[i]-1,所以还要判断一下这个回文串长度是否为 0;
if(i - s_len[i] + == && s_len[i] - > )
visit1[cnt1++] = i;
if(i + s_len[i] - == len- && s_len[i] - > )
visit2[cnt2++] = i;
}
bool flag = false;
int mid;
for(int i=; i<cnt1; ++i) //for循环的嵌套用来让三段中,第一段和第三段两两配对
{
for(int j=cnt2-; j>=; --j)
{
if(visit1[i] + s_len[visit1[i]] - < visit2[j] - s_len[visit2[j]] + )
          //选出的两段不能有重合,有重合表示中间没字符了
{
mid = ( (visit1[i] + s_len[visit1[i]] - ) + (visit2[j] - s_len[visit2[j]] + ) ) / ;
            //然后取两段中间剩余字符的中点
if(mid - s_len[mid] + <= visit1[i] + s_len[visit1[i]] && s_len[mid]- > )
            //判断以中点为中心的回文串是否完全覆盖了中间所有的字符
{
flag = true; //若覆盖了,则表示可以分成三段回文串
break; //就不需要再继续查找了
}
}
}
if(flag) break;
}
return flag;
} int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%s",a);
int len = Init();
manacher(len); bool T_or_F = judge(len);
if(T_or_F)
cout<<"Yes\n";
else
cout<<"No\n";
}
return ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848