标签:http tps val main turn lca while test string
solved 3 (261/679)
卡了题意,很难受
B Ch’s gift (LCA 或 树链剖分 + 线段树)
E FFF at Valentine (DFS)
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("%s\n",ok ? "yes":"no"); } return 0; }
标签:http tps val main turn lca while test string
原文地址:https://www.cnblogs.com/dowhile0/p/9189964.html