0
点赞
收藏
分享

微信扫一扫

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\n");

continue;

}

GetNext(n2 ,m2);

int Ans = 0;

for(i = 1 ;i <= n1 - n2 + 1 ;i ++)

{

Ans += KMP(m1 ,m2 ,n2 ,i);

}

printf("%d\n" ,Ans);

}

return 0;

}



































举报

相关推荐

0 条评论