poj 3690 字符矩阵匹配----HASH算法

http://poj.org/problem?id=3690

UVA还有一道也是这样的题,LRJ给的算法是AC自动机----我还没写过,今天用HASH搞了这道题

思路很清晰,但是处理起来还因为HASH函数写混WA了几次。。。

文本矩阵n*m    T个匹配矩阵p*q

思路:

1、把每一行处理出长为q的hash值

2、对于1中得到的p个哈希值在算一次哈希,这样就把一个矩阵用一个hash值替代了

3、把所有的匹配矩阵压入multiset,然后对于文本矩阵的每一个p*q的子矩阵,算出矩阵哈希值,从multiset中删去该值

4、ans=T-multiset.size()

本题可以作为字符矩阵匹配模板

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdin)

const ull ba1=9973;
const ull ba2=1e8+7;
const int MAXT=1000+10;
const int MAXP=MAXT;//55;

char text[MAXT][MAXT];
char pat[100+5][MAXP][MAXP];

ull ha[MAXT][MAXT],tmp[MAXT][MAXT];
ull base1[MAXT],base2[MAXT];
int N,M,T,P,Q;

void init()
{
    base1[0]=1;
    base2[0]=1;
    for(int i=1;i<MAXT;i++)
    {
        base1[i]=base1[i-1]*ba1;
        base2[i]=base2[i-1]*ba2;
    }
}

void calhash(char mat[][MAXT],int n, int m)
{
    ull e;
    //行
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<Q;j++)
            tmp[i][j]=(j==0)?mat[i][j]:(tmp[i][j-1]*ba1+mat[i][j]);
        for(int j=Q;j<m;j++)
            tmp[i][j]=tmp[i][j-1]*ba1+mat[i][j]-mat[i][j-Q]*base1[Q];
    }
    //列
    for(int j=Q-1;j<m;j++)
    {
        for(int i=0;i<P;i++)
            ha[i][j]=(i==0)?tmp[i][j]:(ha[i-1][j]*ba2+tmp[i][j]);
        for(int i=P;i<n;i++)
            ha[i][j]=ha[i-1][j]*ba2+tmp[i][j]-tmp[i-P][j]*base2[P];
    }
}

int solve()
{
    multiset<ull>app;
    for(int i=0;i<T;i++)
    {
        calhash(pat[i],P,Q);
        app.insert(ha[P-1][Q-1]);
        /*printf("#T--%d# ",i);
        for(int i=0;i<P;i++)
        {
            for(int j=0;j<Q;j++)
                cout << tmp[i][j] << "/" << ha[i][j]  << "   ";
            putchar('\n');
        }*/

    }
    calhash(text,N,M);
    for(int i=P-1;i<N;i++)
        for(int j=Q-1;j<M;j++)
            app.erase(ha[i][j]);
    return T-app.size();
}

int main()
{
    //IN("poj3690.txt");
    init();
    int ic=0,ans;
    while(~scanf("%d%d%d%d%d",&N,&M,&T,&P,&Q) && N+M+T+P+Q)
    {
        for(int i=0;i<N;i++)
            scanf("%s",text[i]);
        for(int i=0;i<T;i++)
        {
            for(int j=0;j<P;j++)
                scanf("%s",pat[i][j]);
        }
        printf("Case %d: %d\n",++ic,solve());
    }
    return 0;
}

poj 3690 字符矩阵匹配----HASH算法

时间: 2024-08-26 11:48:43

poj 3690 字符矩阵匹配----HASH算法的相关文章

poj 3690 Constellations 矩阵的hash

给定一个n*m矩阵和t个p*q的矩阵,求这t个矩阵有多少个是n*m的子矩阵. 矩阵都是01矩阵,只有'0' '*' 矩阵的hash,先将每行q列hash,得到一个新矩阵,然后再每列p行hash [注意行列hash时候取的magic数不能一样,不然很容易冲突,会WA,最好取2个素数] 这样原矩阵的每个子矩阵都由一个数字代替了,之后用map判断就够了. 注意:不能事先将原矩阵的所有子矩阵hash值存在map里,然后比较,由于子矩阵数量太大会MLE. map里存的应该是t个矩阵的hash值,注意有重复

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.

最快的内容查找算法-----暴雪的Hash算法

暴雪公司有个经典的字符串的hash公式  :先提一个简单的问题,假如有一个庞大的字符串数组,然后给你一个单独的字符串,让你从这个数组中查找是否有这个字符串并找到它,你会怎么做?  有一个方法最简单,老老实实从头查到尾,一个一个比较,直到找到为止,我想只要学过程序设计的人都能把这样一个程序作出来,但要是有程序员把这样的程序交给用户,我只能用无语来评价,或许它真的能工作,但也只能如此了.  最合适的算法自然是使用HashTable(哈希表),先介绍介绍其中的基本知识,所谓Hash,一般是一个整数,通

字符串匹配的KMP算法

html, body { font-size: 15px; } body { font-family: Helvetica, "Hiragino Sans GB", 微软雅黑, "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.6; color: ; background-color: ; margin: 0; padding: 16px 20px; } h1, h2, h

memcache的一致性hash算法使用

一.概述 1.我们的memcache客户端(这里我看的spymemcache的源码),使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同,只是对我们要存储数据的key进行hash计算,分配到不同节点存储.一致性hash算法是对我们要存储数据的服务器进行hash计算,进而确认每个key的存储位置.  2.常规hash算法的应用以及其弊端 最常规的方式莫过于hash取模的方式.比如集群中可用机器适量为N,那么key值为K的的数据请求很简单的应该路由到hash(K

UVA 11019 字符矩阵哈希

思路:以前没做过字符矩阵的哈希,所以这题是看别人博客写的. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set>

全局匹配KMP算法

KMP算法是通过分析模式字符串,预先计算每个位置发生不匹配的时候,所需GOTO的下一个比较位置,整理出来一个next数组,然后在上面的算法中使用. 本全局匹配KMP算法针对串的堆式存储数据结构 # define MAXSIZE 45 //固定next数组的长度 # define OK 1 # define ERROR 0 typedef int Status; //返回状态 //存放匹配字符串的位置 int indexArray[MAXSIZE] = {0}; //记录匹配字符串出现的次数 in

Hash算法总结

1. Hash是什么,它的作用 先举个例子.我们每个活在世上的人,为了能够参与各种社会活动,都需要一个用于识别自己的标志.也许你觉得名字或是身份证就足以代表你这个人,但是这种代表性非常脆弱,因为重名的人很多,身份证也可以伪造.最可靠的办法是把一个人的所有基因序列记录下来用来代表这个人,但显然,这样做并不实际.而指纹看上去是一种不错的选择,虽然一些专业组织仍然可以模拟某个人的指纹,但这种代价实在太高了. 而对于在互联网世界里传送的文件来说,如何标志一个文件的身份同样重要.比如说我们下载一个文件,文

[算法系列之二十六]字符串匹配之KMP算法

一 简介 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 二 基于部分匹配表的KMP算法 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含搜索串"ABCDABD"? 步骤1:字符串"BBC ABC