hdu 6599 I Love Palindrome String (迴文樹 + 雜湊/manacher)
阿新 • • 發佈:2020-12-24
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6599
利用迴文樹找出所有的迴文串(記錄出現的位置)
然後利用雜湊判斷迴文串的一半是否也是迴文串即可
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 300010; const ull base = 131; int n, tot; int tail, last; ull has[maxn], rhash[maxn], po[maxn]; int ans[maxn]; struct PAM{ int len, fail, son[30], sz, pos; }t[maxn]; char s[maxn]; int Get_Fail(int x){ while(s[tail - t[x].len - 1] != s[tail]) x = t[x].fail; return x; } void Extend(int x){ int cur = Get_Fail(last); if(!t[cur].son[x]){ ++tot; t[tot].len = t[cur].len + 2; t[tot].fail = t[Get_Fail(t[cur].fail)].son[x]; t[tot].pos = tail; t[cur].son[x] = tot; } ++t[t[cur].son[x]].sz; last = t[cur].son[x]; } void count(){ for(int i = tot ; i >= 2 ; --i){ t[t[i].fail].sz += t[i].sz; } } ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; } int main(){ po[0] = 1; for(int i = 1 ; i <= 300000 ; ++i) po[i] = po[i - 1] * base; while(scanf("%s", s + 1) != EOF){ memset(t, 0, sizeof(t)); memset(ans, 0, sizeof(ans)); memset(rhash, 0, sizeof(rhash)); memset(has, 0, sizeof(has)); n = strlen(s + 1); for(int i = 1 ; i <= n ; ++i) has[i] = has[i - 1] * base + s[i] - 'a'; rhash[n + 1] = 0; for(int i = n ; i >= 1 ; --i) rhash[i] = rhash[i + 1] * base + s[i] - 'a'; t[0].len = 0, t[1].len = -1; t[0].fail = t[1].fail = 1; last = 1; tot = 1; for(tail = 1 ; tail <= n ; ++tail){ Extend(s[tail] - 'a'); } count(); for(int i = 2 ; i <= tot ; ++i){ int len2 = (t[i].len & 1) ? t[i].len / 2 + 1 : t[i].len / 2; int len = len2 / 2; int mid = t[i].pos - ((t[i].len & 1) ? ((t[i].len / 2) + 1) : t[i].len / 2) + 1; // printf("%d %d %d\n", t[i].pos, t[i].len, mid); int HR = has[t[i].pos] - has[t[i].pos - len] * po[len]; int HL = rhash[mid] - rhash[mid + len] * po[len]; if(HL == HR){ ans[t[i].len] += t[i].sz; } } for(int i = 1 ; i <= n ; ++i) { if(i == 1) printf("%d", ans[i]); else printf(" %d", ans[i]); } puts(""); } return 0; }