bzoj 3676 回文串 manachar+hash
考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串。
所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串。
最后拓扑排序递推就行了。。。
这道题丧心病狂卡哈希。。。。wa了一屏。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<map> 7 #define bas 131 8 #define bs 31 9 #define p 1000000007 10 #define p2 986598521 11 #define ll long long 12 #define N 1200005 13 using namespace std; 14 char c[N],s[N*3]; 15 int hui[N],n; 16 ll hash[N],pw[N],hash2[N],pw2[N]; 17 int head[1000005],nxt[N],tot,len[N],size[N],zhi[N]; 18 ll key[N],key2[N],nx[N],nx2[N]; 19 void insert(ll x,ll xx,int l,ll z,int ss,ll ww) 20 { 21 int y=x%1000003; 22 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; 23 return ; 24 } 25 int find(ll x,ll xx) 26 { 27 int y=x%1000003; 28 for(int i=head[y];i;i=nxt[i]) 29 { 30 if(key[i]==x&&key2[i]==xx)return i; 31 } 32 return 0; 33 } 34 int head2[N],ver2[N],nxt2[N],tot2; 35 void add2(int x,int y) 36 { 37 tot2++;nxt2[tot2]=head2[x];head2[x]=tot2;ver2[tot2]=y;return ; 38 } 39 void manachar() 40 { 41 int mx=0,id=0; 42 for(int i=1;i<=n;i++) 43 { 44 if(i>mx) 45 { 46 hui[i]=1; 47 mx=i;id=i; 48 } 49 else 50 { 51 hui[i]=min(hui[id-(i-id)],mx-i+1); 52 } 53 int l=i-hui[i],r=i+hui[i]; 54 while(l!=0&&r!=n+1&&s[l]==s[r]) 55 { 56 hui[i]++; 57 mx=i+hui[i]-1; 58 id=i; 59 l--;r++; 60 } 61 int tmp=hui[i]; 62 if(s[i+hui[i]-1]=='#')tmp--; 63 if(tmp==0)continue; 64 int pos2=tmp+i-1,pos1=i-tmp+1; 65 int lenn=(pos2-pos1)/2+1; 66 ll haha,haha2; 67 ll ha=(hash[pos2/2]-(hash[pos1/2-1]*pw[lenn])%p+p)%p; 68 ll ha2=(hash2[pos2/2]-(hash2[pos1/2-1]*pw2[lenn])%p2+p2)%p2; 69 if(pos2==pos1||pos2==pos1+2)haha=0,haha2=0; 70 else haha=(hash[pos2/2-1]-(hash[pos1/2]*pw[lenn-2])%p+p)%p,haha2=(hash2[pos2/2-1]-(hash2[pos1/2]*pw2[lenn-2])%p2+p2)%p2; 71 int k=find(ha,ha2); 72 if(!k)insert(ha,ha2,lenn,haha,pos2/2,haha2),size[tot]++; 73 else size[k]++; 74 } 75 } 76 queue<int>qu; 77 int ru[N]; 78 ll ans; 79 void tupu() 80 { 81 for(int i=1;i<=tot;i++)if(!ru[i])qu.push(i); 82 while(!qu.empty()) 83 { 84 int tmp=qu.front();qu.pop(); 85 ans=max(ans,(ll)size[tmp]*len[tmp]); 86 for(int i=head2[tmp];i;i=nxt2[i]) 87 { 88 ru[ver2[i]]--; 89 size[ver2[i]]+=size[tmp]; 90 if(!ru[ver2[i]])qu.push(ver2[i]); 91 } 92 } 93 } 94 int main() 95 { 96 scanf("%s",c+1); 97 n=strlen(c+1); 98 pw[0]=1;pw2[0]=1; 99 for(int i=1;i<=n;i++)pw[i]=(pw[i-1]*bas)%p; 100 for(int i=1;i<=n;i++)pw2[i]=(pw2[i-1]*bs)%p2; 101 for(int i=1;i<=n;i++)hash[i]=(hash[i-1]*bas+c[i]-'a'+1)%p; 102 for(int i=1;i<=n;i++)hash2[i]=(hash2[i-1]*bs+c[i]-'a'+1)%p2; 103 for(int i=1;i<=n*2+1;i++) 104 { 105 if(i&1)s[i]='#'; 106 else s[i]=c[i/2]; 107 } 108 n=n*2+1; 109 manachar(); 110 for(int i=1;i<=tot;i++) 111 { 112 if(nx[i]==0)continue; 113 int tmp=find(nx[i],nx2[i]); 114 if(tmp!=0)add2(i,tmp),ru[tmp]++; 115 else 116 { 117 ll now,now2; 118 if(len[i]<=4)now=0,now2=0; 119 else 120 { 121 now=(hash[zhi[i]-2]-(hash[zhi[i]-len[i]+2]*pw[len[i]-4])%p+p)%p; 122 now2=(hash2[zhi[i]-2]-(hash2[zhi[i]-len[i]+2]*pw2[len[i]-4])%p2+p2)%p2; 123 } 124 insert(nx[i],nx2[i],len[i]-2,now,zhi[i]-1,now2); 125 add2(i,tot);ru[tot]++; 126 } 127 } 128 tupu(); 129 printf("%lld\n",ans); 130 return 0; 131 }