BZOJ1966 VIRUS病毒检测
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('\n');}
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\n",ans);
return 0;
}
「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」