zoukankan      html  css  js  c++  java
  • POJ1204 Word Puzzles

    传送门

    这题果然是AC自动机的大好题!

    题目的大意是,给定一个l*c的大网格,每个格子里有一个字符,每个格子可以向八个方向形成字符串,问给定的字符串在哪里能被匹配以及在网格中出现的方向(A代表北,然后依次顺时针转)

    解题思路还好想,而且特别暴力:把给定的字符串建成一个AC自动机,之后对于大网格,把八个方向上所能形成的每一个串(一行,列,对角线)都视为文本串放进去匹配,然后记录一下匹配到的位置。

    然而听着你就不想写对不对?!

    不过其实还好,把AC自动机建出来之后,我们没必要写8种情况,我们开一个像宽搜一样记录当前方向下一步与当前值的横纵坐标之差,之后我们在匹配的时候,我们把起始点的坐标和匹配方向传入,在里面像bfs一样一直往下匹配,匹配到了就把答案记录一下。

    传入起始点的话我们需要枚举每一个边上的点,枚举每一个方向。

    还有就是这个题的数据范围明显暧昧不清,都不告诉单词有多长,一开始我数组开小RE了,然后调大(大概600000)才过的。

    我不会告诉你我一开始没搜出来是因为方向写反了

    代码其实不长,真的,才120行。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<vector>
    #include<queue>
    #define pb push_back
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 40005;
    const int N = 600005;
    const ll mod = 1000000007;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    queue <int> q;
    
    struct ans
    {
        int id,x,y,fx,fy,nd;
        char di;
    }a[1005];
    
    char s[1005][1005],b[1005];
    int l,C,w,dx[9] = {0,-1,-1,0,1,1,1,0,-1},dy[9] = {0,0,1,1,1,0,-1,-1,-1};
    
    struct ACG
    {
        int c[N][26],val[N],id[N],cnt,fail[N],le[N];
        void insert(char *p,int d)
        {
            int l = strlen(p),u = 0;
            rep(i,0,l-1)
            {
            int v = p[i] - 'A';
            if(!c[u][v]) c[u][v] = ++cnt;
            u = c[u][v];
            }
            val[u]++,id[u] = d,le[u] = l-1;
        }
        void getfail()
        {
            rep(i,0,25) if(c[0][i]) fail[c[0][i]] = 0,q.push(c[0][i]);
            while(!q.empty())
            {
            int k = q.front();q.pop();
            rep(i,0,25)
            {
                if(c[k][i]) fail[c[k][i]] = c[fail[k]][i],q.push(c[k][i]);
                else c[k][i] = c[fail[k]][i];
            }
            }
        }
        void query(int posx,int posy,int dir)
        {
            int kx = posx,ky = posy,u = 0;
            while(1)
            {
            int v = s[kx][ky] - 'A';
            u = c[u][v];
            for(int t = u;t && val[t] != -1;t = fail[t])
            {
                if(val[t])
                {
                int px = kx - le[t] * dx[dir],py = ky - le[t] * dy[dir];
                a[id[t]].x = px,a[id[t]].y = py,a[id[t]].di = dir + 'A' - 1;
                a[id[t]].fx = posx,a[id[t]].fy = posy,a[id[t]].nd = dir;
                val[t] = -1;
                }
            }
            kx += dx[dir],ky += dy[dir];
            if(kx < 0 || kx > l-1 || ky < 0 || ky > C-1) break;
            }
        }
    }AC;
    int main()
    {
        l = read(),C = read(),w = read();
        rep(i,0,l-1) scanf("%s",s[i]);
        rep(i,1,w) scanf("%s",b),AC.insert(b,i);
        AC.getfail();
        rep(i,0,l-1)
        {
        AC.query(i,0,3),AC.query(i,C-1,7);//k = 0
        AC.query(i,0,2),AC.query(i,C-1,6);//k = 1
        AC.query(i,0,4),AC.query(i,C-1,8);//k = -1
        }
        rep(i,0,C-1)
        {
        AC.query(0,i,5),AC.query(l-1,i,1);//k = INF
        AC.query(0,i,6),AC.query(l-1,i,2);//k = 1
        AC.query(0,i,4),AC.query(l-1,i,8);//k = -1
        }
        rep(i,1,w) printf("%d %d %c
    ",a[i].x,a[i].y,a[i].di);
        //%d %d %d
    ",a[i].x,a[i].y,a[i].di,a[i].fx,a[i].fy,a[i].nd);
        return 0;
    }
  • 相关阅读:
    【SQL】行转列
    【SQL】高级函数汇总
    VisualStudio优秀扩展插件推荐
    【SQL】多行转一列 FOR XML PATH
    【SQL】判断一个字符串是否在另外一个字符串中
    【NodeJS】Windows环境初始化
    【WPF】实现加载中动画效果
    C# ffmpeg简单帮助类
    ZSH出现问题
    Manjaro 安装后的配置
  • 原文地址:https://www.cnblogs.com/captain1/p/9770070.html
Copyright © 2011-2022 走看看