zoukankan      html  css  js  c++  java
  • POJ 1204 Word Puzzles(AC自动机)

    这题的数据卡在,如下:

    5 5 3
    ABCDE
    FGHIJ
    KLMNO
    PQRST
    UVWXY
    PQR
    RS
    RST
    

    puzzle中间的行中可以包含要查询的多个单词。这个问题很好解决,SearchDfa的时候别return就行了,一直搜到字符串的结尾。
    但是这样做也有一个bug,如果数据是这样的:

    4 7 5
    ABCDEFG
    HIJKLMN
    OPQRSTU
    VWXYZAK
    
    RSTU
    STU
    TU 
    JKL
    KL
    

    也就是说查询单词里面,大单词包含着小单词,实际上是很难处理的。我的一个设想是遇到所有危险节点的时候,都访问,该节点的所有前缀节点,并记录该前缀的位置信息,也就是要搜索的单词。这个搜索的时候同样不能return,因为小单词后面可能有大单词。
    不过也可以搜索所有的点,每个点的8个方向都搜索一下,不过时间开销太大。
    对于这题的输入其实很好处理,每一个单词都设置一个唯一的标号,然后构造tire的时候,在每个叶子节点上标记上这个唯一个标号。这样就是唯一的表示,不需要再这个单词的每一个字符上都标志它的标号,因为其他单词来的时候还得改,没用。

    代码
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #include <queue>
    using namespace std;
    
    const int maxn=1010;
    const int LETTERS=26;
    int nNodesCount=0;
    int str_num=-1,l,c,w;;
    
    struct CNode {
        CNode * pChilds[LETTERS];
        CNode * pPrev;
        bool bBadNode;
        int num;
        void Init() {
            memset(pChilds,0,sizeof(pChilds));
            pPrev=NULL;
            bool bBadNode=false;
        }
    };
    
    CNode Tree[maxn*maxn];
    char puzzle[maxn][maxn];
    char words[maxn][maxn];
    int loc[maxn][3];
    int d[8][2]={{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};
    int pd[8]={0,4,6,2,7,1,5,3};
    //上下左右 左上 右上 左下 右下 
    
    void Insert(CNode * pRoot,char * s,int num)
    {
        for (int i=0;s[i];i++) {
            if (pRoot->pChilds[s[i]-'A']==NULL) {
                pRoot->pChilds[s[i]-'A']=Tree+nNodesCount;
                nNodesCount++;
            }
            pRoot=pRoot->pChilds[s[i]-'A'];
        }
        pRoot->bBadNode=true;
        pRoot->num=num;
    }
    
    void BuildDfa()
    {
        for (int i=0;i<LETTERS;i++) {
            Tree[0].pChilds[i]=Tree+1;
        }
        Tree[0].pPrev=NULL;
        Tree[1].pPrev=Tree;
        deque<CNode *> q;
        q.push_back(Tree+1);
        while (!q.empty()) {
            CNode * pRoot=q.front();
            q.pop_front();
            for (int i=0;i<LETTERS;i++) {
                CNode * p=pRoot->pChilds[i];
                if (p) {
                    CNode * pPrev=pRoot->pPrev;
                    while (pPrev) {
                        if (pPrev->pChilds[i]) {
                            p->pPrev=pPrev->pChilds[i];
                            if (p->pPrev->bBadNode) {
                                p->bBadNode=true;
                            }
                            break;
                        }
                        else {
                            pPrev=pPrev->pPrev;
                        }
                    }
                    q.push_back(p);
                }
            }
        }
    }
    
    void SearchDfa(int x,int y,int dir)
    {
        CNode * p=Tree+1;
        while (x>=0&&x<l&&y>=0&&y<c) {
        	while (true) {
                if (p->pChilds[puzzle[x][y]-'A']) {
                    p=p->pChilds[puzzle[x][y]-'A'];
                    if (p->bBadNode) {
                    	int len=strlen(words[p->num]);
                    	loc[p->num][0]=x-(len-1)*d[dir][0];
                    	loc[p->num][1]=y-(len-1)*d[dir][1];
                    	loc[p->num][2]=pd[dir];
                    }
                    break;
                }
                else {
                    p=p->pPrev;
                }
            }
            x+=d[dir][0];
            y+=d[dir][1];
    	}
    }
    
    int main()
    {
        nNodesCount=2;
        
        scanf("%d%d%d",&l,&c,&w);
        for (int i=0;i<l;i++) {
            scanf("%s",puzzle[i]);
        }
        for (int i=0;i<w;i++) {
            scanf("%s",words[i]);
            Insert(Tree+1,words[i],i);
        }
        BuildDfa();
    	
    	for (int i=0;i<l;i++) {
    		for (int k=0;k<8;k++) {
    			SearchDfa(i,0,k);
    			SearchDfa(i,c-1,k);
    		}
    	}
    	
    	for (int j=0;j<c;j++) {
    		for (int k=0;k<8;k++) {
    			SearchDfa(0,j,k);
    			SearchDfa(l-1,j,k);
    		}
    	}
    	
        for (int i=0;i<w;i++) {
            printf("%d %d %c
    ",loc[i][0],loc[i][1],loc[i][2]+'A');
        }
        return 0;
    }
    
    /*
    5 5 3
    ABCDK
    EFGHN
    IJKLS
    MNOPD
    QRSTP
    
    
    4 7 5
    ABCDEFG
    HIJKLMN
    OPQRSTU
    VWXYZAK
    
    RSTU
    STU
    TU 
    JKL
    KL
    
    */
    
    
  • 相关阅读:
    接口测试该怎么做
    Mac操作Github实现代码的下载、上传
    Django开发基础--操作数据库
    Django开发基础--创建项目/应用
    Python统计安卓log中Anr、Crash出现的数量
    Mac下PyCharm快捷键大全
    Selenium常用方法及函数、txt参数化
    Appium基于PO模型
    Selenium免登录、等待、unittest、PO模型
    Python接口请求及封装
  • 原文地址:https://www.cnblogs.com/xyqxyq/p/12328883.html
Copyright © 2011-2022 走看看