hdu3531

Match

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 918    Accepted Submission(s): 298


Problem Description
There is a matrix of size n*n whose elements are either 0 or 1. Now your task is to find out that given a matrix of size m*m whose elements are also 0 or 1 whether it is a sub-matrix of the previous matrix.
 

Input
There is a matrix of size n*n whose elements are either 0 or 1. Now your task is to find out that given a matrix of size m*m whose elements are also 0 or 1 whether it is a sub-matrix of the previous matrix.
 

Output
If the second matrix is a sub-matrix of the first one, print “Yes” on a single line. Otherwise print “No”.
 

Sample Input
4 2 0 0 0 1 0 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 3 2 0 0 1 0 1 0 1 0 0 0 0 1 1
 

Sample Output
Yes No

好题,昨天刚学了rabin_karp ,还是字符串匹配算法 (求t在p中的位置 ,令m=strlen(t))
其实就是hash嘛,
根据horner法则【霍纳法则】来hash
horner法则百度去

我们hash出了t的值
然后我们要求出p中所有连续的长度为m的串的hash值
这个过程我们可以用horner法则推出一个关系式,相邻的两个长度为m的串的hash值之间的关系
这个自己推一下就好了,
所以我们求下一个hash值时候可以通过关系式直接求出,常数时间,
知道我们求出一个hash值与t的hash值相等,或者找不到

效率不解释了

这个题硬搞可以卡时过
然后我们可以用rk搞
上面讲的是rk是一维的,这个显然是二维的
怎么办呢,我们可以压缩成一维的啊

不解释,这个跟动归中的最小子矩阵和,等有异曲同工之妙

上个垃圾的rk代码


#include <cstdio>
#include 
<cstdlib>
#include 
<cstring>
#include 
<cmath>
#include 
<ctime>
#include 
<cassert>
#include 
<iostream>
#include 
<sstream>
#include 
<fstream>
#include 
<map>
#include 
<set>
#include 
<vector>
#include 
<queue>
#include 
<algorithm>
#include 
<iomanip>
using namespace std;
int getv(char x)
{
    
return (x-'0');
}
int rk(char t[],char p[],int d)
{
    
int n=strlen(t);
    
int m=strlen(p);
    
long long h=(long long )pow(double(d),m-1);
    
int pp=0;
    
int tt=0;
    
for(int i=0;i<m;i++)
    {
        pp
=d*pp+getv(p[i]);
        tt
=d*tt+getv(t[i]);
    }
    
for(int s=0;s<=n-m;s++)
    {
        cout
<<"pp,tt is"<<pp<<","<<tt<<endl;
        
if(pp==tt)
            
return s;
        
if (s<n-m)
        {
            tt
=getv(t[s+m])+d*(tt-h*getv(t[s]));
        }
    }
    
return -1;
}
int main()
{
    
char set1[15]={"0123456789"};//串由0 - 9 组成
    char set2[30]={"abcdefghijklmnopqrstuvwxyz"};
    
char p[10]={"2365"};
    
char t[]={"258569236589780"};
    
int d=10;
    
int i=rk(t,p,d);
    printf(
"pos %d\n",i);
    
return 0;
}

code

#include <cstdio>
#include 
<cstdlib>
#include 
<cstring>
#include 
<cmath>
#include 
<ctime>
#include 
<cassert>
#include 
<iostream>
#include 
<sstream>
#include 
<fstream>
#include 
<map>
#include 
<set>
#include 
<vector>
#include 
<queue>
#include 
<algorithm>
#include 
<iomanip>  
#define maxn 1005
#define mod 10003
#define r 2
using namespace std;
int n,m;
int a[maxn][maxn],b[maxn][maxn];
int pb[maxn];
int tmp[maxn];
int tv;
void ready()
{
    pb[
0]=1;
    
for(int i=1; i<=1000; i++) pb[i]=2*pb[i-1% mod;
}
int main()
{
    
int i,j,p,q,ans;
    ready();
    
while(scanf("%d%d",&n,&m)!=EOF)
    {
        
for(i=1; i<=n; i++)
            
for(j=1; j<=n; j++)
                scanf(
"%d",&a[i][j]);
        
for(i=1; i<=m; i++)
            
for(j=1; j<=m; j++)
                scanf(
"%d",&b[i][j]);
        tv
=0;
        
for(i=1; i<=m; i++)
        {
            tmp[i]
=0;
            
for(j=1; j<=m; j++)
                tmp[i]
=(tmp[i]*r+b[j][i])% mod;
            tv
=(tv*r+tmp[i])%mod;
        }
        memset(tmp,
0,sizeof(tmp));
        
for(j=1; j<=n; j++)
        {
            tmp[j]
=0;
            
for(i=1; i<=m; i++)
                tmp[j]
=(tmp[j]*r+a[i][j])%mod;
        }
        
bool flag;
        flag
=0;
        
for(i=m; i<=n&&!flag; i++)
        {
            ans
=0;
            
for(j=1; j<=n&&!flag; j++)
                
if(j<m)
                {
                    ans
=(ans*r+tmp[j])%mod;
                }
                
else
                {
                    ans
=((ans-tmp[j-m]*pb[m-1])*r+tmp[j])%mod;
                    
if((ans+mod)%mod==tv)
                    {
                        
if(a[i][j]==b[m][m]&&a[i][j-m+1]==b[m][1]&&a[i-m+1][j]==b[1][m]&&a[i-m+1][j-m+1]==b[1][1])
                            flag
=1;
                        
else flag=0;
                        
for( p=1; p<=m&&flag; p++)
                            
for(q=1; q<=m&&flag; q++)
                            {
                                
if(b[p][q]!=a[i-m+p][j-m+q])
                                {
                                    flag
=0;
                                    
break;
                                }
                                
if(flag==0break;
                            }
                    }
                }
            
if(i<n)
            {
                
for(j=1; j<=n; j++)
                    tmp[j]
=((tmp[j]-a[i-m+1][j]*pb[m-1])*r+a[i+1][j])%mod;
            }
        }
        
if(flag)
            printf(
"Yes\n");
        
else printf("No\n");
    }
    
return 0;
}



posted on 2012-07-19 23:21 jh818012 阅读(95) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年7月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿

文章档案(85)

搜索

最新评论