COJ 2498 - Boggle AC自动机+DFS

            题意:

                    给了M个单词(M<=100000,单词长度至多为8,单词仅由大写字母构成)..现在给出若干个4*4的字符矩阵(仅含大写字母)..可以从该矩阵任意一个位置出发..不走重复格子的往周围八个方向前进....并且给出了各种长度所能获得的分数.问能获得的最大分数是多少?.至多能走出多少个单词?走出最长的单词是...

            题解:

                    So easy了. 先把这些单词拿来做一个AC自动机...恶心的是空间..我试了好几次才能不ML又不RE..然后就是DFS了..边走边走AC自动机...值得注意的可能有重复的单词..所以要用数组记录一下..


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include <stack>
#include<queue>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define ll long long
#define pi acos(-1.0)
#define MAXN 400005 
using namespace std;    
struct node
{
      int son[26],fail,w;
}P[MAXN];
char ss[8],M[4][4];
bool had[MAXN],used[4][4];
int len[MAXN],T[9]={0,0,0,1,1,2,3,5,11},NUM[MAXN];
int F[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
string s[MAXN]; 
queue<int> Q;
void Build_AC()
{
      int i,h,k;
      for (i=0;i<26;i++)
          if (P[0].son[i]) Q.push(P[0].son[i]);
      while (!Q.empty())
      {
             h=Q.front(),Q.pop(); 
             for (i=0;i<26;i++)
             {
                   k=P[h].fail;
                   while (k && !P[k].son[i]) k=P[k].fail;
                   P[P[h].son[i]].fail=P[k].son[i];
                   if (!P[h].son[i]) P[h].son[i]=P[k].son[i];
                               else  Q.push(P[h].son[i]); 
             }
      }     
}
bool cmp(string a,string b)
{
      if (a.length()!=b.length()) return a.length()>b.length();
      return a<b;      
}
void dfs(int y,int x,int h,int step)
{
      int t,k;
      if (step>8 || y<0 || x<0 || y==4 || x==4 || used[y][x]) return; 
      used[y][x]=true;
      k=h=P[h].son[M[y][x]-'A'];
      while (k) had[P[k].w]=true,k=P[k].fail;
      for (t=0;t<8;t++) 
          dfs(y+F[t][0],x+F[t][1],h,step+1); 
      used[y][x]=false;
}
int main()
{        
      int n,i,q,j,t,h,x,ans,num;   
      memset(P,0,sizeof(P));
      scanf("%d",&n);
      for (i=1;i<=n;i++) scanf("%s",ss),s[i]=ss;
      sort(s+1,s+1+n,cmp);
      num=0;
      for (t=1;t<=n;t++)
      {
              len[t]=s[t].length(),NUM[t]=h=0;
              for (i=0;i<len[t];i++)
              {
                       x=s[t][i]-'A';
                       if (!P[h].son[x]) P[h].son[x]=++num;
                       h=P[h].son[x];
              }
              if (!P[h].w) P[h].w=t,NUM[t]=1;
                      else NUM[P[h].w]++;
      }
      Build_AC();
      scanf("%d",&q);
      while (q--)
      {
              for (i=0;i<4;i++) scanf("%s",M[i]);     
              memset(had,false,sizeof(had));
              memset(used,false,sizeof(used));
              for (i=0;i<4;i++) 
                 for (j=0;j<4;j++)
                    dfs(i,j,0,1); 
              for (t=1;t<=n;t++) 
                 if (had[t]) break;
              num=ans=0;
              for (i=1;i<=n;i++)
                 if (had[i]) ans+=NUM[i]*T[len[i]],num+=NUM[i];
              printf("%d %s %d\n",ans,s[t].c_str(),num);                 
      }
      return 0;
}


你可能感兴趣的:(COJ 2498 - Boggle AC自动机+DFS)