zoukankan      html  css  js  c++  java
  • UVA11019KMP(二维矩阵匹配出现次数)

    题意:
        给你两个矩阵,一个大的一个小的,然后问你这个小矩阵在大的矩阵里出现了多少次?
    思路:
          说好了AC自动机的,我自己尝试写了个暴力的KMP竟然过了,AC自动机自己的模板还没写完,就暂时没用,说下KMP的解法吧,首先我们考虑如果是一维的情况,是不是就直接KMP裸题了,那么我们就想办法把二维降成一维,我用的是比较笨的方法就是把每一数列看成一个字母(每次比较的时候要比较一数列),求出next数组,然后在把大的那个串暴力拆成一些小串,宽度是他自己的宽度,长度是和小串长度一样,然后线性的去KMP就行了,一开始只是抱着试试的态度,毕竟时间复杂度最坏的情况太高,但是试的原因是这样的,在处理串匹配的时候时间往往并没有那么多,是可以根据概率算出来,就算是最笨的匹配方式,匹配失败就从头从新匹配,在随机数据的情况下也是很少的,并不能简单的(m+n*m)/2这样算,当时我的想法是如果这样超时了,我会去尝试把比较那个地方优化下,就是把两个串比较的那个地方,感觉string去处理可能会快一点(没有尝试),如果还超时那就只能把自己上午没写完的那个AC自动机模板写完(写了两天了,写的比较痛苦),然后在做了。不过没想到1A了。



    #include<stdio.h>
    #include<string.h>

    char stra[1002][1002];
    char strb[102][102];
    int next[102];

    bool jude(int a ,int b ,int n)
    {
        for(int i = 1 ;i<= n ;i ++)
        if(strb[i][a] != strb[i][b])
        return 0;
        return 1;
    }


    bool jude2(int a ,int b ,int I ,int k)
    {
        for(int i = 1 ;i <= k ;i ++)
        if(stra[i+I-1][a] != strb[i][b])
        return 0;
        return 1;
    }

    void GetNext(int n ,int m)
    {
        int j = 0 ,k = -1;
        next[0] = -1;
        while(j < m)
        {
            if(k == -1 || jude(j ,k ,n))
            next[++j] = ++k;
            else k = next[k];
        }
    }

    int KMP(int n ,int m ,int k ,int I)
    {
        int i ,j ,Ans = 0;
        for(i = j = 0 ;i < n ;)
        {
            if(jude2(i ,j ,I ,k))
            {
                if(j == m - 1) Ans ++;
                i ++ ,j ++;
            }
            else
            {
                j = next[j];
                if(j == -1)
                {
                    i ++ ,j = 0;
                }
            }
        }
        return Ans;
    }


    int main ()
    {
        int t ,n1 ,m1 ,n2 ,m2 ,i;
        scanf("%d" ,&t);
        while(t--)
        {
            scanf("%d %d" ,&n1 ,&m1);
            for(i = 1 ;i <= n1 ;i ++)
            scanf("%s" ,stra[i]);
            scanf("%d %d" ,&n2 ,&m2);
            for(i = 1 ;i <= n2 ;i ++)
            scanf("%s" ,&strb[i]);
            if(n2 > n1 || m2 > m1)
            {
                printf("0 ");
                continue;
            }
            GetNext(n2 ,m2);
            int Ans = 0;
            for(i = 1 ;i <= n1 - n2 + 1 ;i ++)
            {
                Ans += KMP(m1 ,m2 ,n2 ,i);
            }
            printf("%d " ,Ans);
        }
        return 0;
    }































  • 相关阅读:
    在windows下安装环回适配器(Microsoft Loopback Adapter)
    c#中的 ? 与 ??
    MVC中提交包含HTML代码的页面处理方法
    Linux(CentOS)日常操作命令
    MySql命令行下导出、导入数据
    NHibernate中text类型字段太长时被截断解决办法
    windows7下修改hosts文件无效解决办法
    IIS与Apache同时使用80端口
    因为数据库正在使用,所以无法获得对数据库的独占访问权 SQL 2005 / SQL 2008
    在windows64位服务器上运行windows32位机器上开发的asp.net应用程序
  • 原文地址:https://www.cnblogs.com/csnd/p/12062537.html
Copyright © 2011-2022 走看看