poj 1204 Word Puzzles

/*

题意: 给定一个L*C的单词表,给定W个单词,查找每个单词匹配的起始坐标位置,题目保证有解
可以沿着8个方向进行查找: A 代表正北,顺时针依次是 B(东北),C(正东),...

思路: 如果将单词表建 trie 树,这样数据规模会太大,
所以要对查找的单词建 trie 树,然后将单词表拿到 trie 数组中搜索,
枚举单词表的每个位置作为匹配的起始位置,再枚举8个方向进行查找,
如果能从根节点搜索到叶节点,说明该叶节点表示的这个单词存在,也就找到该单词匹配的起始坐标位置和方向
要是中途遇到为空的trie节点,则表示没有单词与之匹配,就不必要再继续往下查找了

*/

#include <iostream> // trie树
using namespace std ;
struct Node
{
int next[26];
int pos; //记录该节点代表的单词在W个单词里的位置,从0到W-1, -1则表示不存在该单词
}table[1000000];

int L,C,W;
int mv[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
// 第一项{-1,0}代表正北,顺时针依次旋转

int ans[1005][3],found[1005]; //ans[i]记录查找到的第i个单词的信息,found[i]标记第i个单词是否已找到
int count,suc; //count标记已经找到多少个单词了,suc标记所有W个单词是否都已找到
int cur;

void init()
{
memset(table[0].next,-1,sizeof(table[0].next));
cur=1;
}
void insert(char ch[],int pos)
{
Node* p=&table[0];
for(int i=0;ch[i];++i)
{
int j=ch[i]-'A';
if(p->next[j]==-1)
{
p->next[j]=cur++;
Node* q=&table[p->next[j]];
for(int k=0;k<26;++k)
q->next[k]=-1;
q->pos=-1; //标记该节点代表的单词没有出现过
}
p=&table[p->next[j]];
}
p->pos=pos;
}
char words[1005][1005]; //words为单词表
void search(int x,int y,int dir)
{
Node* p=&table[0];
int k=words[x][y]-'A';
int start_x=x,start_y=y;
while(p->next[k]!=-1)
{
p=&table[p->next[k]];
if( p->pos!=-1 && !found[p->pos] )
{
found[p->pos]=1; //第一次找到该单词
ans[p->pos][0]=start_x; //记录这个单词匹配的起始坐标位置和查找的方向
ans[p->pos][1]=start_y;
ans[p->pos][2]=dir;
count++;
if(count==W)
{
suc=1; //表示查找完毕
break;
}
}
x+=mv[dir][0];
y+=mv[dir][1];
if( ! ( x>=0&&x<L&&y>=0&&y<C) )
break;
k=words[x][y]-'A';
}
}
int main()
{
init();
scanf("%d%d%d",&L,&C,&W);
for(int i=0;i<L;++i)
{
scanf("%s",words[i]);
}
char ch[1005];
for(int i=0;i<W;++i)
{
scanf("%s",ch);
insert(ch,i);
}
for(int x=0; x<L && !suc ;++x)
{
for (int y=0; y<C && !suc ;++y)
{
for(int dir=0; dir<8 && !suc ;++dir)
{
search(x,y,dir);
}
}
}
for(int i=0;i<W;++i)
printf("%d %d %c\n",ans[i][0],ans[i][1],ans[i][2]+'A');
return 0 ;
}

posted on 2011-07-22 16:21  sysu_mjc  阅读(128)  评论(0编辑  收藏  举报

导航