2017 全国多校第九场 训练日志
solved 3 (261/679) ? 卡了题意,很难受 ? B?Ch’s gift?(LCA? 或? 树链剖分 + 线段树) ? ? E?FFF at Valentine?(DFS) ? ? F?Senior Pan? ? ? H?Numbers ? ? J?Two strings?(记忆化搜索 /? dp / 正则表达式 ) 题意:给一个s串,由大小写字母组成,给一个t串,由大小写字母和‘ . ‘和‘ * ‘组成,其中点可以替换任何字符,星可以改变前面那个字符的任意长度(0到正无穷),能否匹配s和t? 思路:记忆化搜索 1.dfs(i,j)表示s[i]和t[j]匹配 那么对于t[j],分3种情况 1.1 : t[j]为‘ . ‘那么,我们可以dfs(i+1,j+1),表示i和j匹配成功,那么用掉i和j之后,比较(i+1,j+1),同时,注意在dfs下去之前,把t[j]修改成s[i],在dfs结束之后修改回‘ . ‘ 1.2 : t[j]为星,首先可以跳过这个星串,直接dfs(i,j+2)。 接下来,我们只需要: 看i是否和j-1匹配,如果匹配,dfs(i+1,j),表示*保留着继续搜,dfs(i+1,j+1),表示*不保留了。 1.3 : t[j]== s[i] 直接往下搜便可 dfs(i+1,j+1) 如果t[j+1]是星,那么我们还可以dfs一次dfs(i,j+2) ? 判断可行的标准有: i和j都超出了s串和t串的长度 i超出长度,j刚好在t串尾部,且尾部为星 i超出长度,j在尾部-1的位置,且尾部为星 由于每种情况搜了一次就不再继续搜,所以复杂度是O(2500*2500*T) ? #include <bits/stdc++.h> using namespace std; string s,t; int ok; bool vis[2600][2600]; int dfs(int i,int j){ if(vis[i][j])return vis[i][j]; if(i==s.size()&&j==t.size()){ ok=1; return vis[i][j]=1; } if(i==s.size()&&j==t.size()-1&&t[j]==‘*‘){ ok=1; return vis[i][j]=1; } if(i==s.size()&&j==t.size()-2&&t[j+1]==‘*‘){ ok=1; return vis[i][j]=1; } if(ok){ return vis[i][j]=1; } if(i==s.size())return vis[i][j]=-1; if(t[j]==‘.‘){ t[j]=s[i]; vis[i+1][j+1]=dfs(i+1,j+1); t[j]=‘.‘; if(j+1<t.size() && t[j+1]==‘*‘){ vis[i][j+2]=dfs(i,j+2); } } else if(t[j]==‘*‘){ vis[i][j+1]=dfs(i,j+1); if(t[j-1]==‘.‘){ vis[i+1][j]=dfs(i+1,j); vis[i+1][j+1]=dfs(i+1,j+1); }else{ if(s[i]==t[j-1]){ vis[i+1][j+1]=dfs(i+1,j+1); vis[i+1][j]=dfs(i+1,j); } } } else { if(s[i]==t[j]){ vis[i+1][j+1]=dfs(i+1,j+1); } if(j+1<t.size() && t[j+1]==‘*‘){ vis[i][j+2]=dfs(i,j+2); } } } int main(){ int T;cin>>T; while(T--){ memset(vis,0,sizeof vis); cin>>s>>t; ok=0; dfs(0,0); printf("%sn",ok ? "yes":"no"); } return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |