Matrix Matcher UVA - 11019 (AC自动机)

Given anNMmatrix, your task is to nd the number of occurences of anXYpattern.

Input

The rst line contains a single integert(t15), the number of test cases.

For each case, the rst line contains two integersNandM(N;M1000). The nextNlinescontainMcharacters each.

The next line contains two integersXandY(X;Y100). The nextXlines containYcharacterseach.

Output

For each case, output a single integer in its own line, the number of occurrences.

Sample Input

2

1 1

x

1 1

y

3 3

abc

bcd

cde

2 2

bccd

Sample Output

0

2

http://fastvj.rainng.com/problem/UVA-11019 

题目大意:给出一个大的二维字符矩阵T,一个小的二维矩阵P,问P在T中存在的次数。

解题思路:思路很简单,使用一个二维矩阵cnt,如果cnt[r][c]表示T中以(r,c)为左上角、与P等大的矩形有多少个完整的行和P对应位置的行完全相同。当P的第j行出现在T的第r行、起始列号为i时,意味着cnt[r-j+1][i-y+2]++,其中具体加几和存储的起始位置有关,按照自己的规则即可。所有匹配结束后,那些cnt[r][c] == x(P的行数)的点就是一个二维匹配点。另外需要注意的是P中可能存在重复,存在重复的模板会导致字典树中结点编号覆盖,所以使用一个vector数组保存所有的编号。

/*
@Author: Top_Spirit
@Language: C++
*/
#include 
using namespace std ;
typedef unsigned long long ull ;
typedef long long ll ;
typedef pair < int, int > P ;
const int Maxn = 1e5 + 10 ;
const int INF = 0x3f3f3f3f ;
const double PI = acos(-1.0) ;
const ull seed = 133 ;
const int _Max = 1000 + 10 ;

int Next[Maxn][26], fail[Maxn], cnt[_Max][_Max], tot ;
vector < int > ve[Maxn] ;
string t[Maxn], p[Maxn] ;

void Insert(string s, int index){
    int root = 0 ;
    for (auto i : s){
        int id = i - 'a' ;
        if (!Next[root][id]) Next[root][id] = ++tot ;
        root = Next[root][id] ;
    }
    ve[root].push_back(index);
}

void getFail (){
    queue < int > que ;
    for (int i = 0; i < 26; i++){
        if (Next[0][i]){
            fail[Next[0][i]] = 0 ;
            que.push(Next[0][i]) ;
        }
    }
    while (!que.empty()){
        int tmp = que.front() ;
        que.pop() ;
        for (int i = 0; i < 26; i++){
            if (Next[tmp][i]) {
                fail[Next[tmp][i]] = Next[fail[tmp]][i] ;
                que.push(Next[tmp][i]) ;
            }
            else Next[tmp][i] = Next[fail[tmp]][i] ;
        }
    }
}

void query(string s, int r, int y){
    int root = 0, p = root ;
    for (int i = 0; s[i]; i++){
        int id = s[i] - 'a' ;
        while (p && !Next[p][id]) p = fail[p] ;
        if (!p) p = root ;
        p = Next[p][id] ;
        for (int k = 0; k < ve[p].size(); k++){
            int j = ve[p][k] ;
            if (r - j + 1 > 0) cnt[r - j + 1][i - y + 2]++ ;
        }
    }
}

int Count(int n, int m, int x){
    int ans = 0 ;
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            if (cnt[i][j] == x) ans++ ;
        }
    }
    return ans ;
}

int n, m, x, y ;

int main (){
    int T ;
    cin >> T ;
    while (T--){
        cin >> n >> m ;
        tot = 0 ;
        for (int i = 1; i <= n; i++) cin >> t[i] ;
        memset(Next, 0, sizeof(Next)) ;
        memset(cnt, 0, sizeof(cnt)) ;
        memset(fail, 0, sizeof(fail)) ;
        for (int i = 0; i < Maxn; i++) ve[i].clear() ;
        cin >> x >> y ;
        for (int i = 1; i <= x; i++) {
            cin >> p[i] ;
            Insert(p[i], i) ;
        }
        getFail() ;
        for (int i = 1; i <= n; i++){
            query(t[i], i, y) ;
        }
        cout << Count(n, m, x) << endl ; ;
    }
    return 0;
}

 

你可能感兴趣的:(AC自动机,strings)