【文文殿下】[BZOJ4327] JSOI2012 玄武密碼
阿新 • • 發佈:2018-11-21
SAM裸題。這道題卡空間。要小心數組別開炸了。
#include<cstdio> #include<cstring> typedef long long ll; const int maxn = 2e7+20; int par[maxn],mx[maxn],tr[maxn][4]; int cnt=1,last=1; inline int change (char ch) { if(ch=='E') return 0; else if(ch=='S') return 1; else if(ch=='W') return 2; else return 3; } void extend(int x) { int np = ++cnt,p=last; mx[np]=mx[p]+1; last=np; while(p&&!tr[p][x]) tr[p][x]=np,p=par[p]; if(!p) par[np]=1; else { int q = tr[p][x]; if(mx[q]==mx[p]+1) { par[np]=q; } else { int nq = ++cnt; mx[nq]=mx[p]+1; memcpy(tr[nq],tr[q],sizeof tr[q]); par[nq]=par[q];par[q]=par[np]=nq; while(p&&tr[p][x]==q) tr[p][x]=nq,p=par[p]; } } return; } int n,m; char A[10000010]; inline void solve(int len) { int ans = 0,cur=1; for(int i = 1;i<=len;++i) { int tmp = change(A[i]); if(tr[cur][tmp]) { cur = tr[cur][tmp]; } else {printf("%d\n",i-1);break; } if(i==len) printf("%d\n",i); } } int main() { scanf("%d%d",&n,&m); scanf("%s",A+1); for(int i = 1;i<=n;++i) extend(change(A[i])); while(m--) { scanf("%s",A+1); int len = strlen(A+1); solve(len); } return 0; }