您的位置:首页 > 其它

Ball Blasting Game UVA - 12378 (马拉车)

2017-09-19 20:21 288 查看
题意:给一个字符串,然后可以选择一个字符消除,消除的位置两边会合并起来,当合并起来的相同字符大于等于二,则可以将相同字符消除,消除的位置两边可以继续合并,直到不能合并为止。问选择一个字符消除,最多可以消除几次

分析:先将相邻相同的写成一个字符,然后用马拉车求出最长回文串长度P,ans=(P+1)/2;

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>

using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 220000+10;

char s1[maxn],s[maxn];
char s2[maxn];
int p[maxn];
int first(char *s1,char *s2)
{
int len=1,i=0;
s2[0]='$';
while(s1[i]!='\0')
{
s2[len++]='#';
s2[len++]=s1[i++];
}
s2[len++]='#';
return len;
}
void Manacher(int *p,char *str,int len)
{
memset(p,0,sizeof(p));
int mx=0,id=0;
for(int i=0;i<len;i++)
{
p[i]=mx>i?min(p[2*id-i],mx-i):1;
while(str[i+p[i]]==str[i-p[i]]) p[i]++;
if(i+p[i]>mx)
{
mx=i+p[i];
id=i;
}
}
}

void init()
{
mem(s,'\0');mem(s1,'\0');mem(s2,'\0');
}
int main()
{
int n;scanf("%d",&n);
while(n--)
{
init();
scanf("%s",s);
int len=strlen(s),h=0;
s1[h++]=s[0];
for(int i=1;i<len;i++)
if(s[i]!=s[i-1])
s1[h++]=s[i];
len=first(s1,s2);
Manacher(p,s2,len);
int ans=1;
for(int i=0;i<len;i++)
ans=max(ans,p[i]);
printf("%d\n",ans/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: