• UVA 11019 二维匹配 AC自动机


    这个题目要求在一个大矩阵里面匹配一个小矩阵,是AC自动机的灵活应用

    思路是逐行按普通AC自动机匹配,用过counts[i][j]记录一下T字符矩阵以i行j列为开头的与P等大的矩阵区域 有多少行已经匹配了,显然如果该数值==p的行数,则说明匹配成功

    就是在自动机的过程中,匹配得时候要稍微多想一下,每次匹配都要调用函数对 counts进行维护,以及还要注意某些行是相同的情况,用个链表保存,匹配成功后直接链过去继续对counts进行维护

    最后统计counts里面有多少个值==p的行数即可得出结果

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int N = 1010;
    char T[N][N];
    char  word[N][N];
    int x,y,n,m;
    int cnt,tr;
    int recline[N];
    int next[N];
    int len[N];
    int counts[N][N];
    
    void process_match(int pos, int v) //对counts进行维护
    {
        int pr=recline[v-1];
        int c=pos-len[pr]+1;//得到矩阵行和列的数值
        while (pr>=0){
            if (tr>=pr){
                counts[tr-pr][c]++;
            }
           pr=next[pr];//直接对下一个相同的行进行该操作
        }
    }
    struct ACTrie
    {
        int ch[N*10][30];
        int last[N*10];
        int val[N*10];
        int f[N*10];
        int sz;
        int idx(char c){
               return c-'a';
            }
        void init(){
            memset(ch,0,sizeof ch);
            memset(last,0,sizeof last);
            memset(val,0,sizeof val);
            memset(f,0,sizeof f);
            sz=1;
        }
        void insert(char*s,int v){
            int u=0;
            for (int i=0;s[i];i++){
                int c=idx(s[i]);
                if (!ch[u][c]){
                   ch[u][c]=sz++;
                }
                u=ch[u][c];
            }
            val[u]=v;
        }
        void getfail(){
            queue<int> q;
            for (int i=0;i<26;i++)
            {
                int u=ch[0][i];
                if (u) q.push(u);
            }
            while (!q.empty()){
                int u=q.front();
                q.pop();
                for (int i=0;i<26;i++){
                    int v=ch[u][i];
                    if (!v) continue;
                    q.push(v);
                    int p=f[u];
                    while (p && !ch[p][i]) p=f[p];
                    f[v]=ch[p][i];
                    last[v]=val[f[v]]?f[v]:last[f[v]];
                }
            }
        }
        void report(int pos,int j){ //匹配函数要改一下,每次匹配成功都调用该函数对counts进行维护
            if (j){
                process_match(pos, val[j]);
                report(pos, last[j]);
            }
        }
        void find(char* str){
            int u=0;
            for (int i=0;str[i];i++){
                int c=idx(str[i]);
                while (u && !ch[u][c]) u=f[u];
                u=ch[u][c];
                if (val[u]){
                    report(i,u);
                }
                else if (last[u])
                    report(i,f[u]);
            }
    
        }
    
    } ACT;
    int main()
    {
        int t;
        scanf("%d",&t);
        while (t--){
            scanf("%d%d",&x,&y);
            for (int i=0;i<x;i++){
                scanf("%s",T[i]);
            }
            scanf("%d%d",&n,&m);
            ACT.init();
            for (int i=0;i<n;i++){
                scanf("%s",word[i]);
                recline[i]=i;
                next[i]=-1;
                len[i] = strlen(word[i]);
                for (int j=0;j<i;j++){
                    if (strcmp(word[i],word[j])==0){
                        recline[i]=j;
                        next[i]=next[j]; //用链表的方式保存相同的行
                        next[j]=i;
                        break;
                    }
                }
                if (recline[i]==i){
                    ACT.insert(word[i],i+1);
                }
            }
            ACT.getfail();
            memset(counts,0,sizeof counts);
            for (tr=0;tr<x;tr++){
                ACT.find(T[tr]);
            }
            int ans=0;
            for (int i=0;i<x-n+1;i++)
                for (int j=0;j<y-m+1;j++){
                //cout<<i<<" !! "<<j<<" "<<counts[i][j]<<endl;
                if (counts[i][j]==n)
                    ans++;
                }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    git常用操作命令
    如何编写高质量代码
    Chrome调试工具简单介绍
    使用eclipse+tomcat搭建本地环境
    chrome设置--disable-web-security解决跨域
    利用Maven管理工程项目本地启动报错及解决方案
    用户输入验证【提升篇】
    简单【用户输入验证】
    【消息框】的返回值
    【消息框】的4种显示形式
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3673737.html
Copyright © 2020-2023  润新知