zoukankan      html  css  js  c++  java
  • [poj] 1204 Word Puzzles || AC自动机

    原题

    给个X*Y的字符串矩阵,W个询问,对每个询问输出这个串出现的位置及方向,共有8个方向,顺时针开始分别用A~H表示

    AC自动机的板子题。
    对于待匹配串建一个自动机,然后从矩阵的四周分别沿八个方向跑,找到一个串的时候就记录答案,但不能退出。

    另:方向要找好啊!!

    #include<cstdio>
    #include<cstring>
    #define N 1010
    using namespace std;
    int x,y,n,ansx[N],ansy[N],d[N],l[N];
    //int dx[10]={0,0,1,1,1,0,-1,-1,-1},dy[10]={0,1,1,0,-1,-1,-1,0,1};
    int dx[10]={0,-1,-1,0,1,1,1,0,-1},dy[10]={0,0,1,1,1,0,-1,-1,-1};
    char t[N][N],s[N],r[10]=" ABCDEFGH";
    struct hhh
    {
        int data;
        hhh *child[26],*fail;
        hhh()
    	{
    	    fail=NULL;
    	    data=0;
    	    for (int i=0;i<26;i++) child[i]=NULL;
    	}
    };
    hhh *root=new hhh;
    hhh *now,*tmp;
    hhh* q[100*1000+10];
    
    void add(int x)
    {
        now=root;
        for (int i=1;i<=l[x];i++)
        {
    	if (now->child[s[i]-'A']==NULL)
    	    now->child[s[i]-'A']=new hhh;
    	now=now->child[s[i]-'A'];
        }
        now->data=x;
    }
    
    void bfs()
    {
        int l=0,r=0;
        root->fail=root;
         for (int i=0;i<26;i++)
        {
    	if (root->child[i]==NULL)
    	    root->child[i]=root;
    	else
    	    root->child[i]->fail=root,q[r++]=(root->child[i]);
        }
        while (r!=l)
        {
    	hhh* nw=q[l++];
    	for (int i=0;i<26;i++)
    	{
    	    if (nw->child[i])
    	    {
    		now=nw->child[i];
    		if (now!=root) q[r++]=now;
    		if (now->fail==NULL) now->fail=nw->fail->child[i];
    	    }
    	    else nw->child[i]=nw->fail->child[i];
    	    if (nw->data==0 && nw->fail->data)
    		nw->data=nw->fail->data;
    	}
        }
    }
    
    void find(int a,int b,int i)
    {
        now=root;
        while (1)
        {
    	if (a<=0 || a>x) break;
    	if (b<=0 || b>y) break;
    	now=now->child[t[a][b]-'A'];
    	tmp=now;
    	while (tmp->data)
    	{
    	    int tp=tmp->data;
    	    ansx[tp]=a-dx[i]*(l[tp]-1);
    	    ansy[tp]=b-dy[i]*(l[tp]-1);
    	    d[tp]=i;
    	    tmp=tmp->fail;
    	}
    	a+=dx[i];
    	b+=dy[i];
        }
    }
    
    int main()
    {
        scanf("%d%d%d",&x,&y,&n);
        for (int i=1;i<=x;i++)
    	scanf("%s",t[i]+1);
        for (int i=1;i<=n;i++)
        {
    	scanf("%s",s+1);
    	l[i]=strlen(s+1);
    	add(i);
        }
        bfs();
        for (int i=1;i<=8;i++)
        {
    	for (int j=1;j<=x;j++)
    	{
    	    find(j,1,i);
    	    find(j,y,i);
    	}
    	for (int j=1;j<=y;j++)
    	{
    	    find(1,j,i);
    	    find(x,j,i);
    	}
        }
        for (int i=1;i<=n;i++)
    	printf("%d %d %c
    ",ansx[i]-1,ansy[i]-1,r[d[i]]);
        return 0;
    }
    
  • 相关阅读:
    n皇后问题
    POJ2155 Matrix二维线段树经典题
    hiho一下 第六十六周
    hdu1754 I hate it线段树模板 区间最值查询
    hdu5481 Desiderium
    自增运算符
    hdu-1823 Luck and Love
    Oracle 函数大全
    对前台传过来的实体是否为空 进行为空校验的N种方法
    IOC和DI的区别详解
  • 原文地址:https://www.cnblogs.com/mrha/p/7992162.html
Copyright © 2011-2022 走看看