您的位置:首页 > 其它

BZOJ 2462: [BeiJing2011]矩阵模板

2016-03-28 21:17 288 查看
Description

给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在原矩阵中出现过。

所谓01矩阵,就是矩阵中所有元素不是0就是1。

Input

输入文件的第一行为M、N、A、B,参见题目描述。

接下来M行,每行N个字符,非0即1,描述原矩阵。

接下来一行为你要处理的询问数Q。

接下来Q个矩阵,一共Q*A行,每行B个字符,描述Q个01矩阵。

Output

你需要输出Q行,每行为0或者1,表示这个矩阵是否出现过,0表示没有出现过,1表示出现过。

HINT

对于100%的数据,A < = 100。

还是想不通为什么数据这么水。。。其实我的程序有个bug,今天考完试才发现,成绩发下来居然水过了,,无语。。

下面说说思路首先字符总数不大,而且字符串较多,且是01串,情况数较少,,一看就是AC自动机啊,对于每一个询问的子矩阵,每行为一个字符串,建一个AC自动机,然后将原矩阵的各行作为一个字符串进行匹配;每匹配一个字符串,就记录下字矩阵的改行是由原矩阵的哪行匹配成功的,,这里由于匹配的数量不知,因此用vector或者直接手动开个栈也行(毕竟数据太弱),,注意,除了字矩阵的第一行外,字矩阵其余行都要在该行的前一行与原矩阵当前行的前一行匹配成功时才记录下匹配信息;直到原矩阵的最后一行如果也匹配成功,,则该矩阵存在于原矩阵中。。

不知道你们有没有发现bug,,那就是匹配矩阵时我只记录了匹配成功的行数信息,保证了每一行都是连续的,,却没有保证列的连续,,因此匹配时有可能发生错位。只要在记录行数的同时再记录一下列数就能解决这个问题了。

以下代码未经修改,,但BZOJ也能水过,有兴趣的可以自己把bug填好。(反正劳资没兴趣。你们随意。)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
struct node {
int ch[2],file;vector<int> count;
node() { file=ch[0]=ch[1]=0; }
}t[1000010];
int head,ans,m,n,a,tot,b,dl[101][1001];char str[1001][1001];
void insert(char str[],int j) {
int now=head;int i=0;
while(i<b) {
int d=str[i]-'0';
if(t[now].ch[d]==0) t[now].ch[d]=tot++;
now=t[now].ch[d];i++;
} t[now].count.push_back(j);return;
}
void bfs() {
int now=head,point=1; queue<int> q; t[head].file=head;
for(int i=0;i<=1;i++) {
if(t[head].ch[i]) {
q.push(t[head].ch[i]);
t[t[head].ch[i]].file=head;
}
else t[head].ch[i]=head;
}
while(!q.empty()) {
int x=q.front();q.pop();
for(int i=0;i<=1;i++) {
if(t[x].ch[i]) {
q.push(t[x].ch[i]);point=t[x].file;
while(t[point].ch[i]==0&&point!=head) point=t[now].file;
t[t[x].ch[i]].file=t[point].ch[i];
}
else t[x].ch[i]=t[t[x].file].ch[i];
}
}
}
void mark(int now,int j) {
int l=t[now].count.size();
for(int i=0;i<l;i++) {
int x=t[now].count[i];
if(x==1) {
dl[x][++dl[x][0]]=j;
if(x==a) ans=1;continue;
}
if(dl[x-1][0]==0) continue;
if(dl[x-1][dl[x-1][0]]==j-1||dl[x-1][dl[x-1][0]-1]==j-1) {
dl[x][++dl[x][0]]=j;
if(x==a) ans=1;
}
} return;
}
void find(char str[],int j) {
int now=head,i=0;
while(i<n) {
int d=str[i++]-'0';
if(t[now].ch[d]) now=t[now].ch[d];
else {
while(!t[now].ch[d]&&now!=head) now=t[now].file;now=t[now].ch[d];
}
if(t[now].count.size()) mark(now,j);
}
}
int main() {
scanf("%d%d%d%d",&m,&n,&a,&b);tot=1;
for(int i=1;i<=m;i++) { scanf("%s",str[i]); }
int q;scanf("%d",&q);
if(b>n||a>m) { while(q--) printf("0\n")
4000
;return 0; }
for(int i=1;i<=q;i++) {
ans=0;head=tot++;
for(int j=0;j<=a;j++) dl[j][0]=0;
for(int j=1;j<=a;j++) { scanf("%s",&str[0]);insert(str[0],j); } bfs();
for(int j=1;j<=m;j++) { if(!ans) find(str[j],j); }
printf("%d",ans);if(i!=q) printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息