A hat’s word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary.
You are to find all the hat’s words in a dictionary.
You are to find all the hat’s words in a dictionary.
Only one case.
a ahat hat hatword hziee word
ahat hatword
先说说我一开始错的思路:首先插入每一个单词,创建字典树,然后遍历查找每一个单词,如果在这个单词中以某一个字母且不是最后一个字母结尾的字母被标记过了,然后把剩下的单词复制给另一个空字符串重新查找,若找到了就输出一整串字符,否则就不输出,这思路听起来好像还挺正确的,但后来我随便写了一组样例过不了,就知道我错哪了,看代码(错误的):
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;
const int mod=1e9+7;
const double pi=acos(-1);
const double eps=1e-8;
const int N=5e4+10;
int trie[N][30],tot;
bool vis[N];
void sert(char s[])
{
int root=0;
for(int i=0;s[i]!='\0';i++)
{
int id=s[i]-'a';
if(!trie[root][id]) trie[root][id]=++tot;
root=trie[root][id];
}
vis[root]=true;
}
bool finf(char s[])
{
bool flag=false;
char ss[30];
int root=0,len=strlen(s);
for(int i=0;s[i]!='\0';i++)
{
int id=s[i]-'a';
if(!trie[root][id]) return false;
root=trie[root][id];
if(vis[root]&&i!=len-1)//以中途的某一个字母结尾
{
flag=true;
strncpy(ss,s+i+1,len-i);//把剩下的串复制给新串
break;
}
}
if(flag)//重新查找新串是否是一个单词
{
root=0;
len=strlen(ss);
for(int i=0;ss[i]!='\0';i++)
{
int id=ss[i]-'a';
if(!trie[root][id]) return false;
root=trie[root][id];
if(vis[root])
{
if(i!=len-1) return false;
else return true;
}
}
}
return false;
}
char s[N][30];
int main()
{
int k=0;
tot=0;
mem(vis,false);
mem(trie,0);
while(~scanf("%s",s[k]))
{
sert(s[k]);
k++;
}
for(int i=0;i<k;i++)
if(finf(s[i]))
printf("%s\n",s[i]);
}这代码看起来是挺好的,但是请看这组样例://输入
a
b
ab
abb
//正确输出
ab
abb
//而我的代码输出是
ab
这下就知道错在哪了,查找abb时,a被标记了,然后开始找bb了,没有找到bb,所以就不输出,而这串字符可以有ab和b组成。
最后我也是看了看网上的思路,暴力拆分每个单词为两个,然后查找,如果两个都找到了,就输出,否则不输出
正确代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;
const int mod=1e9+7;
const double pi=acos(-1);
const double eps=1e-8;
const int N=5e4+10;
int trie[N][30],tot;
bool vis[N];
void sert(char s[])
{
int root=0;
for(int i=0;s[i]!='\0';i++)
{
int id=s[i]-'a';
if(!trie[root][id]) trie[root][id]=++tot;
root=trie[root][id];
}
vis[root]=true;
}
bool finf(char s[])
{
int root=0;
for(int i=0;s[i]!='\0';i++)
{
int id=s[i]-'a';
if(!trie[root][id]) return false;
root=trie[root][id];
}
if(vis[root]) return true;
else return false;
}
char s[N][30];
int main()
{
char a[26],b[26];
int k=0;
tot=0;
mem(vis,false);
mem(trie,0);
while(~scanf("%s",s[k]))
sert(s[k++]);
for(int i=0;i<k;i++)
{
int len=strlen(s[i]);
for(int j=1;j<len;j++)
{
mem(a,'\0');
mem(b,'\0');
strncpy(a,s[i],j);
strncpy(b,s[i]+j,len-j);
if(finf(a)&&finf(b))
{
printf("%s\n",s[i]);
break;
}
}
}
return 0;
}

本文介绍了一个算法问题,即如何找出所有能由字典中其他两个单词组成的单词,并给出了两种实现方法,一种是尝试使用字典树进行匹配,另一种是通过暴力拆分单词并验证其组成部分。
398

被折叠的 条评论
为什么被折叠?



