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;
}































原文地址:https://www.cnblogs.com/csnd/p/12062536.html