Link:
Solution:
可以发现字符串间的关系可以构成一棵树
于是我们先用字符串哈希建树,再树形$dp$即可
设$dp[i][j]$为第$i$个节点从$P$字符串的第$j$为开始匹配的失配位置,
则有$dp[i][j]=dp[ch[i][1]][dp[ch[i][0]][j]]$
在叶子节点时暴力匹配就行了,复杂度$O(k*P)$
Code:
#include <bits/stdc++.h> using namespace std; const int MAXN=505,ML=2005; int T,n,hs[MAXN],dp[MAXN][ML],ch[MAXN][2],root; char S[ML],P[ML],dat[MAXN][ML],tmp[ML],a[ML]; inline int hash(char t[]) { int ret=0; for(int i=0;i<5;i++) ret=ret*27+((i<strlen(t))?(t[i]-'A'+1):0); return ret; } int dfs(int x,int y) { if(dp[x][y]!=-1) return dp[x][y]; if(ch[x][0]) return dp[x][y]=dfs(ch[x][1],dfs(ch[x][0],y)); int k=y; for(int cur=0;k<strlen(P) && cur<strlen(dat[x]);cur++) if(dat[x][cur]==P[k]) k++; return dp[x][y]=k; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n);memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%s%s%s",a,tmp,dat[i]);hs[i]=hash(a); if(dat[i][0]>='a' && dat[i][0]<='z') ch[i][0]=ch[i][1]=0; else { ch[i][0]=hash(dat[i]); scanf("%s%s",tmp,dat[i]); ch[i][1]=hash(dat[i]); } } for(int i=1;i<=n;i++) if(ch[i][0]) for(int j=0;j<2;j++) for(int k=1;k<=n;k++) if(ch[i][j]==hs[k]) ch[i][j]=k; scanf("%s%s",S,P); for(int i=1;i<=n;i++) if(hs[i]==hash(S)) root=i; printf((dfs(root,0)<strlen(P))?"NO ":"YES "); } return 0; }
Review:
如要对字符数组大量比较+判等于,最好使用字符串$Hash$ (采用27进制)
如果不考虑$string$输入效率较低,则对$string$用$map$或$hash\_ map$更优