bzoj 3676 回文串 manachar+hash

考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串。

所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串。

最后拓扑排序递推就行了。。。

这道题丧心病狂卡哈希。。。。wa了一屏。。。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#define bas 131
#define bs 31
#define p 1000000007
#define p2 986598521
#define ll long long
#define N 1200005
using namespace std;
char c[N],s[N*];
int hui[N],n;
ll hash[N],pw[N],hash2[N],pw2[N];
int head[],nxt[N],tot,len[N],size[N],zhi[N];
ll key[N],key2[N],nx[N],nx2[N];
void insert(ll x,ll xx,int l,ll z,int ss,ll ww)
{
int y=x%;
tot++;nxt[tot]=head[y];head[y]=++tot;len[tot]=l;key[tot]=x;nx[tot]=z;zhi[tot]=ss;key2[tot]=xx;nx2[tot]=ww;
return ;
}
int find(ll x,ll xx)
{
int y=x%;
for(int i=head[y];i;i=nxt[i])
{
if(key[i]==x&&key2[i]==xx)return i;
}
return ;
}
int head2[N],ver2[N],nxt2[N],tot2;
void add2(int x,int y)
{
tot2++;nxt2[tot2]=head2[x];head2[x]=tot2;ver2[tot2]=y;return ;
}
void manachar()
{
int mx=,id=;
for(int i=;i<=n;i++)
{
if(i>mx)
{
hui[i]=;
mx=i;id=i;
}
else
{
hui[i]=min(hui[id-(i-id)],mx-i+);
}
int l=i-hui[i],r=i+hui[i];
while(l!=&&r!=n+&&s[l]==s[r])
{
hui[i]++;
mx=i+hui[i]-;
id=i;
l--;r++;
}
int tmp=hui[i];
if(s[i+hui[i]-]=='#')tmp--;
if(tmp==)continue;
int pos2=tmp+i-,pos1=i-tmp+;
int lenn=(pos2-pos1)/+;
ll haha,haha2;
ll ha=(hash[pos2/]-(hash[pos1/-]*pw[lenn])%p+p)%p;
ll ha2=(hash2[pos2/]-(hash2[pos1/-]*pw2[lenn])%p2+p2)%p2;
if(pos2==pos1||pos2==pos1+)haha=,haha2=;
else haha=(hash[pos2/-]-(hash[pos1/]*pw[lenn-])%p+p)%p,haha2=(hash2[pos2/-]-(hash2[pos1/]*pw2[lenn-])%p2+p2)%p2;
int k=find(ha,ha2);
if(!k)insert(ha,ha2,lenn,haha,pos2/,haha2),size[tot]++;
else size[k]++;
}
}
queue<int>qu;
int ru[N];
ll ans;
void tupu()
{
for(int i=;i<=tot;i++)if(!ru[i])qu.push(i);
while(!qu.empty())
{
int tmp=qu.front();qu.pop();
ans=max(ans,(ll)size[tmp]*len[tmp]);
for(int i=head2[tmp];i;i=nxt2[i])
{
ru[ver2[i]]--;
size[ver2[i]]+=size[tmp];
if(!ru[ver2[i]])qu.push(ver2[i]);
}
}
}
int main()
{
scanf("%s",c+);
n=strlen(c+);
pw[]=;pw2[]=;
for(int i=;i<=n;i++)pw[i]=(pw[i-]*bas)%p;
for(int i=;i<=n;i++)pw2[i]=(pw2[i-]*bs)%p2;
for(int i=;i<=n;i++)hash[i]=(hash[i-]*bas+c[i]-'a'+)%p;
for(int i=;i<=n;i++)hash2[i]=(hash2[i-]*bs+c[i]-'a'+)%p2;
for(int i=;i<=n*+;i++)
{
if(i&)s[i]='#';
else s[i]=c[i/];
}
n=n*+;
manachar();
for(int i=;i<=tot;i++)
{
if(nx[i]==)continue;
int tmp=find(nx[i],nx2[i]);
if(tmp!=)add2(i,tmp),ru[tmp]++;
else
{
ll now,now2;
if(len[i]<=)now=,now2=;
else
{
now=(hash[zhi[i]-]-(hash[zhi[i]-len[i]+]*pw[len[i]-])%p+p)%p;
now2=(hash2[zhi[i]-]-(hash2[zhi[i]-len[i]+]*pw2[len[i]-])%p2+p2)%p2;
}
insert(nx[i],nx2[i],len[i]-,now,zhi[i]-,now2);
add2(i,tot);ru[tot]++;
}
}
tupu();
printf("%lld\n",ans);
return ;
}
 
上一篇:Hadoop就是一个别人造好的*


下一篇:vue循环遍历给div添加id