https://www.acwing.com/problem/content/141/
刚学了马拉车算法,找个题目试了一下,然后看题解说这个题目可以用Hash+二,然后就用Hash+二分补了一下,顺便练习一下Hash
如果同马拉车算法来写,直接就套个板子就可以了,但是我在套板子的过程中,如果把数组开到外边,总是出现 segmentation fault,也不知道为啥....
马拉车(140ms):
#include<bits/stdc++.h> using namespace std; const int N=1e6+7; int p[N]; char s[N]; int manacher(string t){ vector<int> p(t.size(), 0); int id = 0; int mx = 0; int resCenter = 0; int resLen = 0; for (int i = 1; i < t.size(); ++i) { p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1; while (t[i + p[i]] == t[i - p[i]]) ++p[i]; if (mx < i + p[i]) { id = i; mx = i + p[i]; } if (resLen < p[i]) { resLen = p[i]; resCenter = i; } } return resLen-1; } int main(){ int time=0; while(cin>>s+1){ if(!strcmp(s+1,"END")) break; string t="&#"; int n=strlen(s+1); for(int i=1;i<=n;i++){ t+=s[i];t+='#'; } printf("Case %d: %d ",++time,manacher(t)); } return 0; }
二分+Hash(396ms)
如果要用二分的话,必须将奇偶数分开来二分,为什么呢?假设最长回文串的个数是奇数个,假设为8,当我们用7来判断的时候,结果可能是无回文串,但是如果用5来判断,一定会有回文串的。
还有一个就是Hash的应用,这里要处理两个哈希值,一个是正着,还有一个是倒着处理。然后在check里边,我们用到了滑动窗口。
code:
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ll; const ll N=1e6+7; ll base=233; char s[N]; ll n; ll ha1[N],ha2[N],p1[N],p2[N]; ll gethash1(ll x,ll y){ return ha1[y]-(ha1[x-1]*p1[y-x+1]); } ll gethash2(ll x,ll y){ return ha2[y]-(ha2[x+1]*p2[n-x+y]); } ll cnt[N]; ll check(ll x){ if(x==0||x==1) return 1; for(ll l=1,r=x;r<=n;r++,l++){ if(gethash1(l,l+x/2-1)==gethash2(r,r-x/2+1)) return 1; } return 0; } int main(){ int time=0; while(cin>>s+1){ n=strlen(s+1); if(!strcmp(s+1,"END")) break; p1[0]=1; for(ll i=1;i<=n;i++){ ha1[i]=ha1[i-1]*base+s[i]; p1[i]=p1[i-1]*base; } p2[n+1]=1; for(ll i=n;i>=1;i--){ ha2[i]=ha2[i+1]*base+s[i]; p2[i]=p2[i+1]*base; } ll pos=0; for(ll i=0;i<=n;pos++,i+=2) cnt[pos]=i; ll l=0,r=pos-1; ll ans=0; while(l<=r){ ll mid=(l+r)/2; if(check(cnt[mid])){ ans=max(cnt[mid],ans); l=mid+1; } else r=mid-1; } pos=0; for(ll i=1;i<=n;pos++,i+=2) cnt[pos]=i; l=0;r=pos-1; while(l<=r){ ll mid=(l+r)/2; if(check(cnt[mid])){ l=mid+1; ans=max(ans,cnt[mid]); } else r=mid-1; } printf("Case %d: %lld ",++time,ans); } return 0; }