【BZOJ】【P3676】【Apio2014】【回文串】【题解】【hash+manacher】

来源:互联网 发布:windows平台fips 编辑:程序博客网 时间:2024/05/29 03:11

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3676

搞了这么久字符串最后还是写了hash……

我写的是ydc大爷说的hash做法

对于一个回文串A,删掉开头结尾的串A'也是回文串,让A'做A的父节点,形成一颗树,然后manacher,把所有极长回文串++,一个串出现的次数就是它以及他的子树和,这样就完了,友情提示,这题卡自然上溢的hash,76个数据就卡了一个点,再加上捆绑数据,apio真是太***

Code:

#include<bits/stdc++.h>#define fst first#define sec secondusing namespace std;const int maxn=1e6+5;typedef pair<int,int> pi;typedef long long LL;typedef unsigned int UL;int n,m,fa[maxn],sum[maxn],f[maxn];char s[maxn],str[maxn];UL hash[maxn],hash_l[maxn],base=233;int hash2[maxn],hash_l2[maxn],base2=97,p=10007;vector<int>G[maxn];LL ans=0;int len[maxn];void hash_init(){hash_l[0]=1;for(int i=1;i<=m;i++)hash_l[i]=hash_l[i-1]*base;hash_l2[0]=1;for(int i=1;i<=m;i++)hash_l2[i]=hash_l2[i-1]*base2%p;UL val=0;int val2=0;for(int i=1;i<=m;i++){val=val*base+str[i]-'a'+1;val2=val2*base2+str[i]-'a'+1;val2%=p;hash[i]=val;hash2[i]=val2;}}int cnt=0;map<pair<UL,int>,int> M;inline int GetHashCode(int l,int r){UL key1=l<=r?hash[r]-hash[l-1]*hash_l[r-l+1]:0;int key2=(l<=r?hash2[r]-hash2[l-1]*hash_l2[r-l+1]%p+p:0)%p;if(M.count(make_pair(key1,key2)))return M[make_pair(key1,key2)];len[++cnt]=r-l+1;return M[make_pair(key1,key2)]=cnt;}void dfs(int u){for(int i=0;i<G[u].size();i++){dfs(G[u][i]);sum[u]+=sum[G[u][i]];}ans=max(ans,(LL)sum[u]*len[u]);}int main(){char c=getchar();s[0]='+';s[++n]='#';while(isalpha(c))str[++m]=c,s[++n]=c,s[++n]='#',c=getchar();s[++n]='-';hash_init();f[1]=1;for(int i=2,k=1;i<=n;i++){if(f[k]+k>i)f[i]=min(f[k+k-i],f[k]+k-i);else f[i]=1;while(s[i+f[i]]==s[i-f[i]]){int l=0,r=0,u=0,v=0;f[i]++;l=(i-f[i]+2)/2;r=(i+f[i]-2)/2;u=GetHashCode(l+1,r-1);v=GetHashCode(l,r);if(v==1||fa[v]==u)continue;fa[v]=u;G[u].push_back(v);}int l=0,r=0,u=0,v=0;l=(i-f[i]+2)/2;r=(i+f[i]-2)/2;v=GetHashCode(l,r);if(v==1)continue;sum[v]++;if(f[k]+k<f[i]+i)k=i;}dfs(1);cout<<ans<<endl;return 0;}


0 0
原创粉丝点击