BZOJ-2462&&2351 矩阵模板&&Matrix 暴力 or Hash orAC自动机 or KMP

来源:互联网 发布:教育行业网络推广方案 编辑:程序博客网 时间:2024/05/20 15:59

2462: [BeiJing2011]矩阵模板
Time Limit: 2 Sec Memory Limit: 128 MB
Submit: 717 Solved: 316
[Submit][Status][Discuss]

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表示出现过。

Sample Input
3 3 2 2
111
000
111
3
11
00
11
11
00
11

Sample Output
1
0
1

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

Source
Day4

.

2351: [BeiJing2011]Matrix
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 740 Solved: 212
[Submit][Status][Discuss]

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表示出现过。

Sample Input
3 3 2 2
111
000
111
3
11
00
11
11
00
11

Sample Output
1
0
1

HINT
对于100%的实际测试数据,M、N ≤ 1000,Q = 1000
对于40%的数据,A = 1。
对于80%的数据,A ≤ 10。
对于100%的数据,A ≤ 100。

Source

题解
2351是2462的数据强化版,对于2462,可以直接暴力;
自己的写法是,记录了一下矩形的0的数目,用二维树状数组的思路,求出子矩阵的0的数目,询问时先比较数目再一一比对;
2462就必须换方法了,这里用的是hash,在做的时候,考虑到了hash,但YY出问题了,大体的思路是:
把每行展成字符串,总之,读入大的矩阵,把大矩阵的每个子矩阵hash,(每个子矩阵的hash值和暴力优化的那个思想很类似),这样每次读入小矩阵可以直接同样的方法hash,与大矩阵的子矩阵比较即可。至于hash的重合概率,TA学长粗略计算是10^-3级的,所以几乎可以无视
同时可以用KMP或者AC自动机的方法,大体就是把一个矩阵的一行或者一列当作一个字符,来实现字符的匹配,自己并不是很会。

code1:(自己的暴力P2462)

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int read(){    int x=0,f=1; char ch=getchar();    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}    return x*f;}int n,m,a,b,q;struct matr{    int a[1010][1010]; int nn,mm; int num0[1010][1010];    matr(){memset(a,0,sizeof(a));memset(num0,0,sizeof(num0));}};struct matri{    int a[110][110]; int nn,mm; int num0[110][110];    matri(){memset(a,0,sizeof(a));memset(num0,0,sizeof(num0));}};matri Mat[1010]; matr Ma;bool pd(int x,int y,int lx,int ly,int now){    bool f=1;    for (int i=x-lx+1; i<=x; i++)        for (int j=y-ly+1; j<=y; j++)            if (Ma.a[i][j]!=Mat[now].a[(i-x+lx)][(j-y+ly)]) {f=0;break;}    return f;}void solve(int now){    bool f=0; int aa=Mat[now].nn,bb=Mat[now].mm;int nn0=Mat[now].num0[aa][bb];    //printf("aa=%d bb=%d\n",aa,bb);    for (int i=aa; i<=n; i++)        for (int j=bb; j<=m; j++)            {                int n0=Ma.num0[i][j]-Ma.num0[i-aa][j]-Ma.num0[i][j-bb]+Ma.num0[i-aa][j-bb];                if (n0==nn0) f=pd(i,j,aa,bb,now);                //printf("NOW=%d i=%d j=%d    n0=%d nn0=%d F=%d\n",now,i,j,n0,nn0,f);                if (f==1) {puts("1");return;}            }    puts("0");}int main(){    n=read();m=read(); a=read();b=read();    Ma.nn=n; Ma.mm=m;    for (int i=1; i<=n; i++)        {            char aaa[1010]; scanf("%s",aaa);            for (int j=1; j<=m; j++)                Ma.a[i][j]=aaa[j-1]-'0';        }    for (int i=1; i<=n; i++)        for (int j=1; j<=m; j++)            if (!Ma.a[i][j])                 Ma.num0[i][j]=Ma.num0[i-1][j]+Ma.num0[i][j-1]-Ma.num0[i-1][j-1]+1;            else Ma.num0[i][j]=Ma.num0[i-1][j]+Ma.num0[i][j-1]-Ma.num0[i-1][j-1];    q=read();    for (int i=1; i<=q; i++)        {            Mat[i].nn=a; Mat[i].mm=b;            for (int j=1; j<=a; j++)                {                    char aaa[1010]; scanf("%s",aaa);                    for (int k=1; k<=b; k++)                        {                            Mat[i].a[j][k]=aaa[k-1]-'0';                            if (!Mat[i].a[j][k])                                 Mat[i].num0[j][k]=Mat[i].num0[j-1][k]+Mat[i].num0[j][k-1]-Mat[i].num0[j-1][k-1]+1;                            else Mat[i].num0[j][k]=Mat[i].num0[j-1][k]+Mat[i].num0[j][k-1]-Mat[i].num0[j-1][k-1];                        }                }        }    for (int i=1; i<=q; i++)        solve(i);    return 0;}

code2:(hash,P2351)by TA学长

#include<cstdio>#include<iostream>using namespace std;#include<cstring>#include<algorithm>const int M=1000+5,N=1000+5,A=100+5,B=1000+5;const int Mod=1e9+7;int mat[N][M];typedef long long LL;int hash[2][N][M],data[N*M];int main(){//  freopen("matrix.in","r",stdin);//  freopen("matrix.out","w",stdout);    int m,n,a,b;    scanf("%d%d%d%d",&n,&m,&a,&b);    char c;    for(int i=0;i<n;++i)        for(int j=0;j<m;++j){            c=getchar();            while(c<'0'||c>'1')c=getchar();            mat[i][j]=c-'0';        }    LL base[2]={1,1};    for(int i=b;i--;)base[0]=(base[0]<<1)%Mod;    for(int i=n;i--;){        for(int j=1;j<=b;++j)hash[0][i][m-b]=((hash[0][i][m-b]<<1)+mat[i][m-j])%Mod;        for(int j=m-b-1;j>=0;--j)hash[0][i][j]=((hash[0][i][j+1]<<1)%Mod-mat[i][j+b]*base[0]+mat[i][j])%Mod;        //for(int j=m-b;j>=0;--j)printf("hash(0,%d,%d)=%d\n",i,j,hash[0][i][j]);    }    for(int i=a;i--;)base[1]=base[1]*base[0]%Mod;    for(int j=m-b;j>=0;--j){        for(int i=1;i<=a;++i)hash[1][n-a][j]=(hash[1][n-a][j]*base[0]+hash[0][n-i][j])%Mod;        for(int i=n-a-1;i>=0;--i)hash[1][i][j]=(hash[1][i+1][j]*base[0]-hash[0][i+a][j]*base[1]+hash[0][i][j])%Mod;    }    int tot=0;    for(int i=n-a;i>=0;--i)        for(int j=m-b;j>=0;--j){            data[tot++]=(hash[1][i][j]+Mod)%Mod;            //printf("hash(1,%d,%d)=%d\n",i,j,data[tot-1]);        }    sort(data,data+tot);    tot=unique(data,data+tot)-data;    int q,tmp;    scanf("%d",&q);    while(q--){        tmp=0;        for(int i=0;i<a;++i)            for(int j=0;j<b;++j){                c=getchar();                while(c<'0'||c>'1')c=getchar();                mat[i][j]=c-'0';            }        for(int i=a;i--;)            for(int j=b;j--;)                tmp=((tmp<<1)+mat[i][j])%Mod;        //printf("%d\n",tmp);        if(data[lower_bound(data,data+tot,tmp)-data]==tmp)puts("1");        else puts("0");    }}
0 0
原创粉丝点击