UVA11019KMP(二维矩阵匹配出现次数)
生活随笔
收集整理的這篇文章主要介紹了
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;
}
? ? 給你兩個矩陣,一個大的一個小的,然后問你這個小矩陣在大的矩陣里出現了多少次?
思路:
? ? ? 說好了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;
}
總結
以上是生活随笔為你收集整理的UVA11019KMP(二维矩阵匹配出现次数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LA3942字典树+递推
- 下一篇: UVA11020 优势人群(multis