您的位置:首页 > 其它

[Manacher+bit]Palindrome

2017-05-16 18:06 113 查看

https://nanti.jisuanke.com/t/15428

题目大意:离散表示的字符串,求其最长回文串长度。

解题关键:若只用Manacher算法,在统计sum时会超时,所以加一个树状数组来维护前n项和,即可AC。

  注意进行Manacher时,i是从1开始的,不要小也不要大。

 n天后更新:以前一直没搞清离线与动态维护的区别,今天终于理解了,此题可以开始直接离线求前n项和,因为以后不再改变,所以此题不需要bit维护。直接用一个数组统计一下前n项和即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
ll num;
char ch;
}s[100010];
ll p[110010],sum[110010],bit[110010];
ll t,n,a,k,id,maxlen,tt;
ll read(ll i){
ll res=0;
while(i){
res+=bit[i];
i-=i&-i;
}
return res;
}
void add1(ll i,ll x){
while(i<110010){
bit[i]+=x;
i+=i&-i;
}
}
int main(){
scanf("%lld",&t);
while(t--){
memset(p,0,sizeof p);
memset(bit,0,sizeof bit);
memset(s,0,sizeof s);
memset(sum,0,sizeof sum);
scanf("%lld",&n);
k=0;
for(int i=0;i<n;i++){
k++;
//cin>>s[k].num>>s[k].ch;
scanf("%lld %c",&s[k].num,&s[k].ch);
tt=s[k].num;
if(s[k].ch==s[k-1].ch){
s[k-1].num+=s[k].num;
k--;
}
add1(k,tt);
}
id=0,maxlen=0;
s[0].ch='*',s[k+1].ch='#';
for(int i=1;i<=k;i++){
if(p[id]+id>i) p[i]=min(p[2*id-i],p[id]+id-i);
else p[i]=1;
while(s[i-p[i]].ch==s[i+p[i]].ch&&s[i-p[i]].num==s[i+p[i]].num)++p[i];
if(p[i]+i>p[id]+id) id=i;
sum[i]=read(i+p[i]-1)-read(i-p[i]);
if(s[i-p[i]].ch==s[i+p[i]].ch) sum[i]+=2*min(s[i-p[i]].num,s[i+p[i]].num);
maxlen=max(maxlen,sum[i]);
}
printf("%lld\n",maxlen);
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: