您的位置:首页 > 其它

UVa:11019 Matrix Matcher(AC自动机)

2014-03-12 09:52 399 查看
AC自动机。

很容易想到一个思路将模式矩阵的每一行插入Tire,然后将匹配矩阵的每一行用AC自动机漫游,统计该行中出现过的模式矩阵行,最后判断出现过的每行是否能够组成整个模式矩阵即可。这个也很好判断。开一个数组flag【i】【j】【k】表示字符【i,j】是第k个字符串的末尾

但是有个问题如果模式矩阵中的串有重复,比如说

匹配阵是

aaa

aaa

aaa

模式矩阵

aa

aa

那么很有可能得不到正确结果。

所以我把AC自动机中的val数组改成了二维,来表示某个字符可能是多个重复字符串的末尾。

注意是字符矩阵,所以只用26个小写字母是不行的。至少得128.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define ll  long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 101*100
#define LIM 128
using namespace std;
char gl1[1005][1005],gl2[105][105];
bool flag[1005][1005][101];
int now,ans;
int nx,ny,mx,my;
struct Tire
{
    int ch[MAXN][LIM],last[MAXN],f[MAXN];
    vector<int> val[MAXN];
    int sz;
    void clear()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        val[0].clear();
    }
    void insert(char *word,int v)
    {
        int u=0;
        for(int i=0; word[i]; ++i)
        {
            int c=word[i];
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz].clear();
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u].push_back(v);
    }
    void process(int i,int j)
    {
        if(j)
        {
            for(int k=0; k<val[j].size(); ++k)
            {
                int v=val[j][k];
                if(v==1||flag[now-1][i+1][v-1]==true)
                {
                    flag[now][i+1][v]=true;
                    if(v==mx) ans++;
                }
            }
            process(i,last[j]);
        }
    }
    void find(char *str)
    {
        int j=0;
        for(int i=0; str[i]; ++i)
        {
            int c=str[i];
            j=ch[j][c];
            if(val[j].size()) process(i,j);
            else if(last[j]) process(i,last[j]);
        }
    }
    void getFail()
    {
        f[0]=0;
        queue<int> que;
        for(int i=0; i<LIM; ++i)
        {
            int u=ch[0][i];
            if(u)
            {
                f[u]=0;
                last[u]=0;
                que.push(u);
            }
        }
        while(!que.empty())
        {
            int q=que.front();
            que.pop();
            for(int i=0; i<LIM; ++i)
            {
                int u=ch[q][i], v=f[q];
                if(!u)
                {
                    ch[q][i]=ch[v][i];
                    continue;
                }
                que.push(u);
                while(v&&!ch[v][i]) v=ch[v][i];
                f[u]=ch[v][i];
                last[u]=val[f[u]].size()?f[u]:last[f[u]];
            }
        }
    }
};
Tire tree;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        tree.clear();
        scanf("%d%d",&nx,&ny);
        for(int i=1; i<=nx; ++i)
        {
            scanf("%s",gl1[i]+1);
            memset(flag[i],0,sizeof(flag[i]));
        }
        scanf("%d%d",&mx,&my);
        for(int i=1; i<=mx; ++i)
        {
            scanf("%s",gl2[i]+1);
            tree.insert(gl2[i]+1,i);
        }
        tree.getFail();
        ans=0;
        for(int i=1; i<=nx; ++i)
        {
            now=i;
            tree.find(gl1[i]+1);
        }
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: