1. 程式人生 > >【HDU】4787 GRE Words Revenge 二進位制分組+AC自動機

【HDU】4787 GRE Words Revenge 二進位制分組+AC自動機

題目傳送門

多次詢問可以按時間分治,但可惜這題強制線上。

因而引入了二進位制分組,就是把當前字串的數量二進位制拆分。

比如說當前有10個字串,就把這10個字串分成一組8個和一組2個。

這樣每個字串最多被重構AC自動機log2n一種優美的暴力

二進位制分組適用於那些不支援修改的資料結構,AC自動機算一例,凸包也是。

附上AC程式碼:

#include <cstdio>
#include <cstring>
#include <set>
#include <string>
#include <queue>
using namespace
std; typedef long long ll; const int N=2e5+10,M=30; struct AC{ int lk[2],nt,c; }ac[N]; int ti,m,len,scnt,ncnt,root[M],sz[M],top; char s[5000010],t[5000010]; set <string> st; string str[N]; queue <int> que; ll ans; inline int newnode(void){return (++ncnt,ac[ncnt].lk[0]=ac[ncnt].lk[1]=ac[ncnt].nt=ac[ncnt].c=0
),ncnt;} inline void build(int x){ ac[x].nt=x; for (int i=0; i<2; ++i) if (ac[x].lk[i]) ac[ac[x].lk[i]].nt=x,que.push(ac[x].lk[i]); else ac[x].lk[i]=x; while (!que.empty()){ int p=que.front();que.pop(); for (int i=0; i<2; ++i) if (ac[p].lk[i]){ ac[ac[p].lk[i]].nt=ac[ac[p].nt].lk[i]; ac[ac[p].lk[i]].c+=ac[ac[ac[p].lk[i]].nt].c; que.push(ac[p].lk[i]); } else
ac[p].lk[i]=ac[ac[p].nt].lk[i]; } return; } inline void ist(char *s){ if (st.count(s+1)) return; st.insert(s+1);str[++scnt]=string(s+1); sz[++top]=1; while (top>1&&sz[top]==sz[top-1]) sz[--top]*=2,ncnt=root[top]-1; root[top]=newnode(); for (int i=scnt-sz[top]+1; i<=scnt; ++i){ int p=root[top]; for (int j=0; j<str[i].size(); ++j){ if (!ac[p].lk[str[i][j]-'0']) ac[p].lk[str[i][j]-'0']=newnode(); p=ac[p].lk[str[i][j]-'0']; } ++ac[p].c; } build(root[top]); } inline ll query(char *s){ ll ret=0; for (int i=1; i<=top; ++i){ int p=root[i]; for (int j=1; s[j]; ++j) p=ac[p].lk[s[j]-'0'],ret+=ac[p].c; } return ret; } int main(void){ for (int i=(scanf("%d",&ti),1); i<=ti; ++i){ scanf("%d",&m),printf("Case #%d:\n",i),ans=0; ncnt=scnt=top=0,memset(root,0,sizeof root),memset(sz,0,sizeof sz),st.clear(); while (m--){ char c=getchar();while (c!='+'&&c!='?') c=getchar(); scanf("%s",t+1),len=strlen(t+1); for (int i=1; i<=len; ++i) s[i]=t[(i+ans-1)%len+1]; s[len+1]=0; if (c=='+') ist(s); else printf("%d\n",ans=query(s)); } } return 0; }