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