文章目录
- 题目描述
- 解析
- 代码
题目描述
解析
做的不错
把trie树真的当成一棵树递归即可
注意一个标记时的问题:
void AC(){int l=strlen(s0+1),pl=1;for(int i=1;i<=l;i++){int a=ask(s0[i]);pl=tr[pl][a];int k=pl;while(k>1){if(ok[k]) break;//注意!ok[k]=1;k=nxt[k];}}
}
原题数据不写这行没关系
但我觉得好像有点问题啊。。。
首先正确性是可以保证的;
要是不加,可能不断重复标记,感觉也许会卡成100n
加上后也快了一倍
也强调一下这个标记往回找不漏的问题,第一交又忘了qwq
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e6+100;
const int M=1e7+100;
int tr[N][5],tot=1;
int n,l;
char s[N],s0[M];
int cnt=0;
int id[N];
int ok[N];
int dep[N],fa[N];
int ask(char c){if(c=='E') return 1;else if(c=='S') return 2;else if(c=='W') return 3;else return 4;
}
void build(int k){int l=strlen(s+1),pl=1;for(int i=1;i<=l;i++){int a=ask(s[i]);if(!tr[pl][a]){tr[pl][a]=++tot;dep[tot]=dep[pl]+1;fa[tot]=pl;}pl=tr[pl][a];}id[k]=pl;//num[pl]++;
}
int q[N],st,ed,nxt[N];
void bfs(){st=ed=q[1]=1;for(int i=1;i<=4;i++) tr[0][i]=1;nxt[1]=0;while(st<=ed){int now=q[st++];for(int i=1;i<=4;i++){if(!tr[now][i]) tr[now][i]=tr[nxt[now]][i];else{q[++ed]=tr[now][i];nxt[tr[now][i]]=tr[nxt[now]][i];}}}return;
}
void AC(){int l=strlen(s0+1),pl=1;for(int i=1;i<=l;i++){int a=ask(s0[i]);pl=tr[pl][a];int k=pl;while(k>1){if(ok[k]) break;ok[k]=1;k=nxt[k];}}
}
int find(int pl){//printf("pl=%d\n",pl);if(pl==1) return 0;if(ok[pl]) return dep[pl];return find(fa[pl]);
}
int main() {scanf("%d%d",&l,&n);scanf("%s",s0+1);for(int i=1;i<=n;i++) scanf("%s",s+1),build(i);bfs();AC();for(int i=1;i<=n;i++){printf("%d\n",find(id[i]));}return 0;
}/*
11 5
EESSWNNSWSE
W
EEN
SSESSW
SSWSSE
SWS
*/