BZOJ1966 VIRUS病毒检测
题解
一道比较神的(Dp),首先我们记(f[i][j])表示模板串匹配到第(i)位,当前病毒串匹配到第(j)位,匹配是否可行。然后我们就可以进行简单的转移了。不过还有带(*)号的情况,所以我们继续记(c[i])表示第(i)位的(*)号匹配到的位置最近的地方是哪里(如果该位置不是(*)号,就设为(inf))。然后我们就可以得到一个复杂度位(O(n*len1*len2))的(Dp)了。但是这似乎是不能过的。。。么?这种玄学复杂度居然在BZOJ这个老年机上居然跑过去了。。不敢相信,可能数据水把,期待更好的做法。。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('
');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=1005;
int n;
char st[maxn],s[maxn];
int f[maxn][500],c[maxn];
/*==================Define Area================*/
int main() {
scanf("%s",st+1);
int L=strlen(st+1);
read(n);
int ans=n;
while(n--) {
scanf("%s",s+1);
int l=strlen(s+1);
memset(f,0,sizeof f);
memset(c,0x3f,sizeof c);
f[0][0]=1;
for(int i=1;i<=L;i++) {
if(st[i]!='*') {
for(int j=1;j<=l;j++) {
if(st[i]=='?'||st[i]==s[j]) {
f[i][j]|=f[i-1][j-1];
if(st[i-1]=='*'&&c[i-1]<j) f[i][j]|=1;
}
}
}
else {
if(i==1) f[1][0]=1;
for(int j=1;j<=l;j++) {
f[i][j]=(f[i-1][j]|f[i][j-1]);
if(f[i][j]) c[i]=min(c[i],j);
}
}
}
if(f[L][l]) ans--;
}
printf("%d
",ans);
return 0;
}