给出一个n行,m列的方格矩阵,每个格子上有一个字母。
如果在方格中可以找到一条路径(任意起点),使其行走路线上的字母连起来可以组成字符串S
那么我们称字符串S在方格矩阵中。
其中路径应满足下列条件:
1、每一步只能走到与其相邻的格子。不能斜着走
2、对于同一个字符串S,已经走过的位置不能重复走,即同一个字符串不能使用坐标为(a,b)的字母两次,但不同的字符串可以同时使用(a,b)
如"eat"、"oath"在下面的4*4的方格矩阵中
现给出Q个Si(1 ≤ i ≤ Q)字符串,请问哪些字符串在方格矩阵中
如果在方格中可以找到一条路径(任意起点),使其行走路线上的字母连起来可以组成字符串S
那么我们称字符串S在方格矩阵中。
其中路径应满足下列条件:
1、每一步只能走到与其相邻的格子。不能斜着走
2、对于同一个字符串S,已经走过的位置不能重复走,即同一个字符串不能使用坐标为(a,b)的字母两次,但不同的字符串可以同时使用(a,b)
如"eat"、"oath"在下面的4*4的方格矩阵中
oaan
etae
ihkr
iflv
现给出Q个Si(1 ≤ i ≤ Q)字符串,请问哪些字符串在方格矩阵中
Description
第一行一个整数T(T ≤ 100),表示有T组测试数据
接下来每组测试数据第一行三个整数n,m,Q,表示矩阵的大小和字符串的个数
n行每行m个字符,表示方格矩阵
接下来Q行,每行一个字符串Ai,Ai长度最大为100 , 1 ≤ n,m,Q ≤ 100
保证数据中的字母皆为小写字母,且字符串Ai不重复
接下来每组测试数据第一行三个整数n,m,Q,表示矩阵的大小和字符串的个数
n行每行m个字符,表示方格矩阵
接下来Q行,每行一个字符串Ai,Ai长度最大为100 , 1 ≤ n,m,Q ≤ 100
保证数据中的字母皆为小写字母,且字符串Ai不重复
Input
输出所有在方格中的字符串Si的序号i,按升序排列。
如果都不在方格中输出空行
如果都不在方格中输出空行
Output
1
2
3
4
5
6
7
8
9
10
11
|
1
4 4 4
oaan
etae
ihkr
iflv
oath
pea
eat
rain
|
Sample Input
1
2
|
1 3
|
题目链接:
http://acm.swust.edu.cn/problem/1201/
分析:
根据所有字符串建立字典树,然后dfs一旦找到一个字符串就从字典树中删除。
代码:
#include <stdio.h>
#include <string.h>
struct Trie
{
Trie *next[26];
Trie *pre;
short index;
short wordIndex;
bool flag;
short v;
}contenct[1000005];
Trie *root;
bool CheckHaveWord(char* word, Trie* rt)
{
if (word[0] == '\0')
{
return rt->flag;
}
if (rt->next[word[0] - 'a'] == NULL)return false;
return CheckHaveWord(word + 1, rt->next[word[0] - 'a']);
}
void RemoveWord(Trie* rt)
{
rt->v--;
Trie* pre = rt->pre;
if (pre == NULL) return;
if (rt->v == 0)
{
pre->next[rt->index] = NULL;
}
RemoveWord(pre);
}
void DeleteWord(Trie* rt)
{
if (rt->flag)
{
rt->flag = false;
RemoveWord(rt);
}
}
char mpt[110][110];
char str[110];
int n, m, q;
bool flag[1100];
int dir[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
bool visit[110][110];
int trienum = 0;
Trie* NewTrie()
{
contenct[trienum].flag = false;
contenct[trienum].v = 0;
contenct[trienum].index = -1;
contenct[trienum].pre = NULL;
for (int i = 0; i < 26; i++)
contenct[trienum].next[i] = NULL;
return &contenct[trienum++];
}
void InsertWord(char* word, Trie* rt, int index)
{
rt->v++;
if (word[0] == '\0')
{
rt->flag = true;
rt->wordIndex = index;
return;
}
if (rt->next[word[0] - 'a'] == NULL)
{
rt->next[word[0] - 'a'] = NewTrie();
rt->next[word[0] - 'a']->pre = rt;
rt->next[word[0] - 'a']->index = word[0] - 'a';
}
InsertWord(word + 1, rt->next[word[0] - 'a'], index);
}
void dfs(int x, int y, Trie* rt)
{
if (rt->flag)
{
flag[rt->wordIndex] = true;
DeleteWord(rt);
}
for (int i = 0; i < 4; i++)
{
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if (tx < 0 || tx >= n || ty < 0 || ty >= m || visit[tx][ty]) continue;
if (rt->next[mpt[tx][ty] - 'a'] == NULL) continue;
visit[tx][ty] = true;
dfs(tx, ty, rt->next[mpt[tx][ty] - 'a']);
visit[tx][ty] = false;
}
}
/*
oaan
etae
ihkr
iflv
*/
int main()
{
int t, i, j;
scanf("%d", &t);
while (t--)
{
trienum = 0;
memset(flag, 0, sizeof(flag));
memset(visit, 0, sizeof(visit));
scanf("%d%d%d", &n, &m, &q);
root = NewTrie();
for (i = 0; i < n; i++)
{
scanf("%s", mpt[i]);
}
for (i = 0; i < q; i++)
{
scanf("%s", str);
InsertWord(str, root, i + 1);
}
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
if (root->next[mpt[i][j] - 'a'] != NULL)
{
visit[i][j] = true;
dfs(i, j, root->next[mpt[i][j] - 'a']);
visit[i][j] = false;
}
}
}
bool k = false;
for (i = 0; i < 1100; i++)
{
if (flag[i])
{
if (k) printf(" %d", i);
else
{
k = true;
printf("%d", i);
}
}
}
printf("\r\n");
}
return 0;
}