版权声明:如果转载,请注明出处。 https://blog.csdn.net/S_999999/article/details/89190034
Three Palindromes
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2051 Accepted Submission(s): 733
Problem Description
Can we divided a given string S into three nonempty palindromes?
Input
First 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
Output
For each case, output the "Yes" or "No" in a single line.
Sample Input
2
abc
abaadada
Sample Output
Yes
No
题目大意:问一个字符串能否分成三个非空回文字符串。
解题思路:
很牛逼15MS就过了,我也不理解为什么,求大佬指点。。。。。。
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 20005
int n;
char d[MAXN];
char st[MAXN*2];
int p[MAXN*2],begi[MAXN*2],tail[MAXN*2];
int len;
void manacher()
{
int MaxId=0,id;
for(int i=0; i<len; 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;
}
p[i] -= 1;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
getchar();
scanf("%s",d);
int l = strlen(d);
len = 0;
st[len++] = '#';
for(int i = 0; i < l; i++){
st[len++] = d[i];
st[len++] = '#';
}
st[len] = 0;
manacher();
int flag = 0;
int pn =0 ,ln = 0;
for(int i = 1; i < len - 1; i++)
{
if(i - p[i] == 0) begi[pn++] = i;
if(i + p[i] == len-1) tail[ln++] = i;
}
for(int i = 0; i < pn; i++){
for(int j = 0; j<=ln - 1; j++){
int s1 = begi[i] + p[begi[i]]+1 ,s2 = tail[j] - p[tail[j]]-1;
if(s1 > s2)
break;
int mid = (s1 + s2)/2;
if(p[mid] >= mid-s1)
{
flag = 1;
break;
}
}
if(flag )
break;
}
if(flag )
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
一般做法:
#include<iostream>
#include<cstring>
using namespace std;
char str[20009],s[40009];
int p[40009],ll[40009],rr[40009];
int len = 0;
void init( ){
int l = strlen( str );
s[0]='$';
s[1]='#';
len = 1 ;
for( int i=0;i<l;i++){
s[++len] = str[i];
s[++len] = '#';
}
s[++len]='\0';
}
void manacher( ){
init( );
int id ,mx=0;
for( int i=1;i<len;i++){
if( i < mx )
p[i] = min( p[id*2-i],mx-i);
else p[i] =1;
while( s[ i - p[i] ] == s[ i + p[i]])
p[i]++;
if( i + p[i] > mx){
mx = i+p[i];
id = i;
}
}
}
int main(void){
int T;
scanf("%d",&T);
while( T-- ){
scanf("%s",str);
manacher();
int l=-1,r=-1;
for( int i=2;i<len-1;i++){
//第一个字符串所有可能的半径
// $#a#a#a#
if( p[i] == i ){
ll[++l] = p[i] ;
}
//第三个字符串所有可能的半径
if( i+p[i] == len ){
rr[++r] = p[i] ;
}
}
//printf("%d %d\n",l,r);
//枚举所有的情况
bool f = false;
for( int i=0 ;i<=l;i++){
int s = ll[i]*2 ;
for( int j=0; j<=r ;j++){
int e = len - rr[j]*2 ;
int mid = ( e+s ) /2;
if( s > e )
continue;
if( p[mid] == 1 )
continue;
if( p[mid] > mid - s ){
f = true;
break;
}
}
if( f ){
break;
}
}
if( f ){
printf("Yes\n");
}
else printf("No\n");
}
return 0;
}