题目大意
给出一个字符串s,由小写字母及 “ ? ” “?” “?”、 “ ∗ ” “*” “∗”组成,其中?代表一个字符,*代表0个或多个字符。
现在给出n个只由小写字母组成的字符串,问这些字符串是否能和s完全匹配?
输出可以与s完全匹配的字符串个数 ( 0 ∼ n ) (0 \sim n) (0∼n)。
思路
动态规划,核心是状态转移。
这道题传递状态的前提也是前一个状态满足。
取现在 s s s中第 i i i个字符, j j j为将匹配的字符串 ( a ) (a) (a)中第 j j j个字符
拿 s s s中第 i i i个字符与 a a a逐个比对
有如下几种情况:
- (在上一个字符成功匹配的前提下) s [ i ] = a [ j ] ∣ ∣ s [ i − 1 ] = ′ ? ′ s[i]=a[j] || s[i-1]='?' s[i]=a[j]∣∣s[i−1]=′?′,这里直接+1
- (在上一个字符成功匹配的前提下) s [ i − 1 ] = ′ ∗ ′ s[i-1]='*' s[i−1]=′∗′且 d p [ i − 1 ] [ j − 1 ] = 1 dp[i-1][j-1]=1 dp[i−1][j−1]=1,从这里以后的都可以匹配
- else 匹配不成功
代码
#include<bits/stdc++.h>
using namespace std;
int n,t;
string s,a;
int dp[100][100];
bool solve(string a)
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;//初始化
for(int i=1;i<=s.length();i++)
{
for(int j=1;j<=a.length();j++)//由于s从0开始,i-1代表现在字符串中的字符
//可以在字符串前插一个字符,保证i和租房有对应
{
if((s[i-1]==a[j-1]||s[i-1]=='?')&&dp[i-1][j-1])
//完全匹配
dp[i][j]=1;
else if(s[i-1]=='*'&&dp[i-1][j-1])
//如果是*,那么之后无论是什么都可以匹配
{
for(int k=j-1;k<=a.length();k++) dp[i][k]=1;
break;
}
}
}
if(dp[s.length()][a.length()]) //整个数组都完全匹配了
return true;
else return false;
}
int main()
{
while(cin>>s)
{
int sum=0;
cin>>n;
while(n--)
{
cin>>a;
if(solve(a)) sum++;
}
cout<<sum<<endl;
}
return 0;
}