题目链接
http://codeforces.com/contest/1023
A. Single Wildcard Pattern Matching
大意
给出一个带有通配符的字符串,问其能否匹配另一个没有带通配符的字符串。
题解
这是一道经典的带通配符的字符串匹配问题。
问号的匹配比较容易,因为问号只能代替一个字符,遇到问号直接匹配即可。但星号却能代替 \(0\) 个或多个字符。
我们可以先判断 * 前的字符串,如果失配,显然可以输出 \(-1\)。
如果遇到 * 号的话,我们可以将星号的位置记录下来,然后从后往前扫描。
当 \(s\) 的长度 \(n\) 与 \(t\) 的长度 \(m\) 满足 \(n>m+1\) 时,说明匹配失败(因为即使 * 代替的内容为空, \(n\) 的最大长度也只是 \(m+1\),当 * 代替的字符串不为空时,显然会满足 \(n \geq m\))。
接下来从后往前扫描时,只要 \(s\) 与 \(t\) 对应的字母相等,当字符串 \(s\) 匹配到 * 时,说明匹配成功。
#include <stdio.h> char s1[200005],s2[200005]; int main() { int n,m; scanf("%d%d",&n,&m); scanf("%s",s1); scanf("%s",s2); int flag=1; for(int i=0;i<=n;i++) if(s1[i]=='*') { flag=-1; break; } else if(s1[i]=='?')continue; else if(s1[i]!=s2[i]) { flag=0; break; } if(flag==1)puts("YES"); else if(flag==0)puts("NO");//比赛的时候这里少打了个else,结果fst了... else { for(int i=n-1,j=m-1;;i--,j--) if(s1[i]=='*') { if(i-1>j)flag=0; else flag=1; break; } else if(s1[i]=='?')continue; else if(s1[i]!=s2[j]) { flag=0; break; } if(flag)puts("YES"); else puts("NO"); } return 0; }
C. Bracket Subsequence
大意
给出一个合法的括号序列,怎样通过删除一些括号,得到一个长度为 \(k\) 的序列。
题解
由于刚开始给出的字符串一定合法,所以刚开始给出的字符串一定有左括号和右括号各 \(n/2\) 个。当然,我们生成的字符串也必须有 \(k/2\) 个左括号和右括号。
我们可以扫描一遍原字符串,如果遇到左括号,且左括号的数量 \(\leq k/2\) 时,就可以把左括号放入答案序列。
如果是右括号,我们需要确保在当前左括号数量小于右括号数量的情况下(左括号数量等于右括号的话,就不能再添加右括号了),在满足右括号数量 \(\leq k/2\) 的情况下,将右括号放入答案序列。
显然,这样的做法不会破坏原来括号的相对顺序,因而这样的做法是合法的。
#include <stdio.h> char s[200005],res[200005]; int main() { int n,k; scanf("%d%d",&n,&k); scanf("%s",s); if(n==k)printf("%s",s); else { int cntl=0,cntr=0,tot=0; for(int i=0;i<n;i++) if(s[i]=='(') { if(cntl!=k/2) { cntl++; res[tot++]='('; } } else { if(cntr!=k/2&&cntl>cntr) { cntr++; res[tot++]=')'; } } printf("%s",res); } return 0; }