就是把字符串转变成一个树,每个节点连接下一个字符,用空间换时间。
对于区分大小写或不区分的题目,只需要改变ch[][26]的值就行了。
ch[u][x]表示u节点(标号决定)下一个x字符节点的标号。
如果题目让记录附加值,那就用val[标号]在插入时记录一下就好了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int maxn=2333; struct trie{ ll ch[maxn][26],siz,val[maxn]; trie(){ siz=1;//一开始的时候只有根节点这一个节点 memset(ch[0],0,sizeof(ch[0])); memset(val,0,sizeof(val)); } inline ll idx(char c){return c-'a';} void insert(char *s,ll v) { ll u=0,len=strlen(s+1); for(ll i=1;i<=len;i++){ ll c=idx(s[i]); if(!ch[u][c]){ memset(ch[siz],0,sizeof ch[siz]); val[siz]=0; ch[u][c]=siz++; } u=ch[u][c]; } val[u]=v; } ll query(char *s) { ll u=0,len=strlen(s+1); for(ll i=1;i<=len;i++){ ll c=idx(s[i]); if(!ch[u][c])return -1; u=ch[u][c]; } return val[u]; } }tr; int main() { return 0; }
P2580 于是他错误的点名开始了
(名字好奇怪)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=10005*50; int n; struct trie { int cnt,ch[maxn][26]; int vis[maxn]; trie() { cnt=1; memset(ch[0],0,sizeof ch[0]); memset(vis,0,sizeof vis); } inline int ex(char c){return c-'a';} inline void insert(char *s) { int u=0,len=strlen(s+1); for(int i=1;i<=len;i++) { int c=ex(s[i]); if(!ch[u][c]){ memset(ch[cnt],0,sizeof ch[cnt]); ch[u][c]=cnt++; } u=ch[u][c]; } } inline int query(char *s) { int u=0,len=strlen(s+1); for(int i=1;i<=len;i++) { int c=ex(s[i]); if(!ch[u][c])return 2; u=ch[u][c]; } if(!vis[u]){ vis[u]++;return 1; } return 3; } }tr; int main() { scanf("%d",&n); char a[100]; for(int i=1;i<=n;i++) { scanf("%s",a+1); tr.insert(a); } int m; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",a+1); switch(tr.query(a)) { case(1):{ printf("OK "); break; } case(2):{ printf("WRONG "); break; } case(3):{ printf("REPEAT "); break; } } } return 0; }