題解 [POI2010]ANT-Antisymmetry
阿新 • • 發佈:2021-12-09
嘗試放到PAM上,跳fail的時候將判斷改成等於,但炸了半個下午
手模後發現一旦有一個元素成為odd的位元組點,它就可能無法被後面的偶長度反迴文串考慮了
於是認為PAM做不了
但我傻了,PAM是可以做的
因為最終的串一定是偶長度的,所以我們可以強制不讓odd有子節點
當跳完fail發現現在跳到了odd時,我們可以直接將now指向even並return
那麼下一個元素就可以選當前點了
點選檢視程式碼
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define N 500010 #define ll long long //#define int long long int n; char s[N]; ll ans; int son[N][2], len[N], fail[N], cnt[N], now, tot; void init() {tot=1; len[1]=-1; fail[0]=fail[1]=1;} int getfail(int u, int i) {while (u!=1 && (i-len[u]-1<1||s[i-len[u]-1]==s[i])) u=fail[u]; return u;} void insert(char c, int i) { // cout<<"ins"<<endl; int u=getfail(now, i), v=c-'0'; if (u==1) {now=0; return ;} if (!son[u][v]) { len[++tot]=len[u]+2; int t=getfail(fail[u], i); fail[tot]=son[t][v]; son[u][v]=tot; // cout<<"add edge: "<<u<<' '<<v<<' '<<tot<<endl; // cout<<"add fail: "<<tot<<' '<<fail[tot]<<endl; } ++cnt[now=son[u][v]]; } signed main() { scanf("%d%s", &n, s+1); init(); for (int i=1; i<=n; ++i) insert(s[i], i); for (int i=tot; i>=2; --i) { cnt[fail[i]]+=cnt[i]; ans+=cnt[i]; } printf("%lld\n", ans); return 0; }