http://www.programming-challenges.com/pg.php?page=downloadproblem&probid=110302&format=html

UVA 10010 Where's Waldorf?(寻找单词)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=31&page=show_problem&problem=951

题目大意:

给出一个由字母组成的m*n矩阵和一份单词列表,在格子中找出每一个可以被找到的单词的位置。

单词必须和矩阵中一条不间断的直线匹配,大小写不敏感(即大写字母和相应的小写字母被认为是相同的)。这个直线可以是水平、竖直、对角线的八个方向之一。

输入:

每组数据,单词矩阵,接下来,k代表带查找的单词。每行一个

输出:

输出匹配的单词的首字母的位置,行和列都从1开始。

相邻两组数据用一个空行隔开。

保证所有单词在表中都可以找到

样例输入:

1

8 11
abcDEFGhigg
hEbkWalDork
FtyAwaldORm
FtsimrLqsrc
byoArBeDeyv
Klcbqwikomk
strEBGadhrb
yUiqlxcnBjf
4
Waldorf
Bambi
Betty
Dagbert
样例输出:
2 5
2 3
1 2
7 8
我的思路:
先求出要查找的反序字符串,然后进行查找,
先横向查找,再竖向查找,最后进行对角查找,在任何一步找到就结束查找
View Code
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;

string word[52];
string str;
string reverse_str;

void reverse(int len)
{
int i;
reverse_str.erase();
for(i=len-1;i>=0;i--)
{
reverse_str+=str[i];
}
}
//// 横向查找
int find_row(int m,int len,int &posi,int &posj)
{
int i,k;
for(i=0;i<m;i++)
{
k=word[i].find(str);
if(k!=string::npos)
{
posi=i;
posj=k;
return 1;
}
k=word[i].find(reverse_str);
if(k!=string::npos)
{
posi=i;
posj=k+len-1;
return 1;
}
}
return 0;
}
//// 竖向查找
int find_col(int m,int n,int len,int &posi,int &posj)
{
string str_tmp;
int i,j,k;
for(j=0;j<n;j++)
{
str_tmp.erase();
for(i=0;i<m;i++)
{
str_tmp+=word[i][j];
}
k=str_tmp.find(str);
if(k!=string::npos)
{
posi=k;
posj=j;
return 1;
}
k=str_tmp.find(reverse_str);
if(k!=string::npos)
{
posi=k+len-1;
posj=j;
return 1;
}
}
return 0;
}
////对角查找
int find_dia(int m,int n,int len,int &posi,int &posj)
{
string str_tmp;
int i,j,pi,pj,k;
for(i=len-1,j=0;i<m;i++) //查找左上部分
{
pi=i;
pj=j;
str_tmp.erase();
while(pi>=0&&pj<n)
{
str_tmp+=word[pi][pj];
pi--;
pj++;
}
k=str_tmp.find(str);
if(k!=string::npos)
{
posi=i-k;
posj=j+k;
return 1;
}
k=str_tmp.find(reverse_str);
if(k!=string::npos)
{
posi=i-k-(len-1);
posj=j+k+len-1;
return 1;
}
}

for(i=0,j=0;j<n-len+1;j++)//查找右上部分
{
pi=i;
pj=j;
str_tmp.erase();
while(pi<m&&pj<n)
{
str_tmp+=word[pi][pj];
pi++;
pj++;
}
k=str_tmp.find(str);
if(k!=string::npos)
{
posi=i+k;
posj=j+k;
return 1;
}
k=str_tmp.find(reverse_str);
if(k!=string::npos)
{
posi=i+k+len-1;
posj=j+k+len-1;
return 1;
}
}

for(i=m-len+1,j=0;i>0;i--) //查找左下部分
{
pi=i;
pj=j;
str_tmp.erase();
while(pi<m&&pj<n)
{
str_tmp+=word[pi][pj];
pi++;
pj++;
}
k=str_tmp.find(str);
if(k!=string::npos)
{
posi=i+k;
posj=j+k;
return 1;
}
k=str_tmp.find(reverse_str);
if(k!=string::npos)
{
posi=i+k+len-1;
posj=j+k+len-1;
return 1;
}
}

for(i=m-1,j=1;j<n-len+1;j++) //查找右下部分
{
pi=i;
pj=j;
str_tmp.erase();
while(pi<m&&pj<n)
{
str_tmp+=word[pi][pj];
pi--;
pj++;
}
k=str_tmp.find(str);
if(k!=string::npos)
{
posi=i-k;
posj=j+k;
return 1;
}
k=str_tmp.find(reverse_str);
if(k!=string::npos)
{
posi=i-k-(len-1);
posj=j+k+len-1;
return 1;
}
}
return 0;
}

void find(int m,int n,int len,int &posi,int &posj)
{
if(find_row(m,len,posi,posj))
return ;
if(find_col(m,n,len,posi,posj))
return ;
if(find_dia(m,n,len,posi,posj))
return ;
}

int main()
{
int T,t;
int i,len,m,n;
int posi,posj;
cin>>T;
while(T--)
{
cin>>m>>n;
cin.get();
for(i=0;i<m;i++)
{
getline(cin,word[i]);
transform(word[i].begin(),word[i].end(),word[i].begin(),::tolower);
}
cin>>t;
cin.get();
for(i=0;i<t;i++)
{
getline(cin,str);
transform(str.begin(),str.end(),str.begin(),::tolower);
len=str.length();
reverse(len);
find(m,n,len,posi,posj);
cout<<posi+1<<' '<<posj+1<<endl;
}
if(T)
cout<<endl;
}
return 0;
}

//另一种方法,对每个位置的字符的八个方向进行符合条件的查找,条件根据长度判定
View Code
#include<iostream>
#include<string>
#include<cstring>
using namespace std;

int dir[8][2]={{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};//方向
int x, y;

string word[52];
string str;

void find(int m, int n)
{
int i,j,k,l;
int dirx,diry,x,y;
int len = str.length();
bool flag[8], cor; //flag为标记哪些方向需要判断
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
if(word[i][j] == str[0] || word[i][j] - str[0] == 32 || word[i][j] - str[0] == -32)//首先判断首字母
{
memset(flag, false, sizeof( flag ));
if((j + 1)>= len)
flag[0] = true;
if((j + 1) >= len && (m - i ) >= len)
flag[1] = true;
if((m - i) >= len)
flag[2] = true;
if((m - i) >= len && (n - j) >= len)
flag[3] = true;
if((n - j) >= len)
flag[4] = true;
if((n - j) >= len && (i + 1) >= len)
flag[5] = true;
if(i >= len)
flag[6] = true;
if((i + 1) >= len && (j + 1) >= len)
flag[7] = true;

for(k = 0; k < 8; k++)
{
if( flag[k] )
{
x = j;
y = i;
dirx = dir[k][0];
diry = dir[k][1];
l = 0;
cor = true;
while(l <len) //对各个字符进行判断
{
if( word[y][x] == str[l] || word[y][x] - str[l] == 32 || word[y][x] - str[l] == -32)
{
x+=dirx;
y+=diry;
l ++ ;
}
else
{
cor = false;
break;
}
}
if( cor )
{
cout<<i+1<<' '<<j+1<<endl;
return ;
}
}
}
}
}
}
}

int main()
{
int T,t;
int m,n,i;
cin>>T;
while(T--)
{
cin>>m>>n;
cin.get();
for(i = 0; i < m; i++)
{
getline(cin,word[i]);
}
cin>>t;
cin.get();
for(i = 0; i < t; i++)
{
getline(cin,str);
find(m,n);
}
if(T>0)
cout<<endl;
}
return 0;
}



posted on 2012-03-07 16:07  pcoda  阅读(270)  评论(0编辑  收藏  举报