题意:
给了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;
}