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('
');}
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;
}
「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」
原文地址:https://www.cnblogs.com/Apocrypha/p/9454767.html