【文文殿下】[BZOJ4327] JSOI2012 玄武密码

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;
}
posted @ 2018-11-21 10:03  文文殿下  阅读(112)  评论(0编辑  收藏  举报