题目大意:给一系列字符串,构成一个词典,然后有若干询问,每个询问为一个字符串x,问字符串是否在词典中,若在则输出x is correct,否则,通过删除x中的某个字符,或者替换x中的某个字符,或者在x中的插入一个字符,使得得到的新字符在词典中,全部输出。输出时要按照词典中字符串的存在顺序。(词典中最多有10000个单词,字符串的长度最大为15,最多有50个询问。)
简单的trie树应用。每个结点存一个bool值,判断其是否是单词。对于删除,替换,插入字符这些操作,只需对询问的字符x的所有这写操作枚举出来,然后在字典树上查找即可。
对于输出,若为correct,直接输出,否则用set把答案存起来,枚举词典中的单词,若在set里,则输出,同时把他在set里删掉。
数组模拟链表:
#include <iostream>
#include <set>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define SIZE 130000
#define N 26
int c[SIZE][N],idx;
int vis[SIZE];
bool isWord[SIZE];
char word[10010][N],input[N];
int tot;
set <string> st;
set <string>::iterator it;
void update(char *str)
{
int len = (int)strlen(str);
int p = 0;
for(int i=0; i<len; i++)
{
vis[p]++;
if(c[p][str[i]-'a'] == 0)
{
++idx;
c[p][str[i]-'a'] = idx;
}
p = c[p][str[i]-'a'];
}
vis[p]++;
isWord[p] = true;
}
bool search(char *str)
{
int len = (int)strlen(str);
int p = 0;
for(int i=0; i<len; i++)
{
if(c[p][str[i]-'a'] == 0)
return false;
p = c[p][str[i]-'a'];
}
return isWord[p];
}
int main()
{
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
memset(isWord,0,sizeof(isWord));
idx = tot = 0;
while(scanf("%s",input))
{
if(strcmp(input,"#") == 0)
break;
update(input);
++tot;
strcpy(word[tot],input);
}
while(scanf("%s",input))
{
if(strcmp(input,"#") == 0)
break;
if(search(input))
printf("%s is correct\n",input);
else
{
int len = (int)strlen(input);
char fuck[N<<1];
int id;
st.clear();
if(len > 1)
{
for(int i=0; i<len; i++) //delete
{
id = 0;
for(int k=0; k<len; k++)
{
if(k == i)continue;
fuck[id++] = input[k];
}
fuck[id] = '\0';
if(search(fuck))
st.insert(fuck);
}
}
for(int i=0; i<len; i++)
{
strcpy(fuck,input);
fuck[len] = '\0';
for(int k=0; k<N; k++)
{
fuck[i] = k+'a';
if(search(fuck))
st.insert(fuck);
}
}
for(int i=0; i<=len; i++)
{
for(int p=0; p<i; p++)
fuck[p] = input[p];
for(int p=i+1; p<=len; p++)
fuck[p] = input[p-1];
for(int k=0; k<N; k++)
{
fuck[i] = k+'a';
fuck[len+1] = '\0';
if(search(fuck))
st.insert(fuck);
}
}
printf("%s: ",input);
if(st.empty())
{
puts("");
continue;
}
for(int i=1; i<=tot; i++)
{
if(st.empty())
break;
it = st.find(word[i]);
if(it != st.end())
{
cout << *it;
st.erase(*it);
if(!st.empty())
printf(" ");
}
}
puts("");
}
}
return 0;
}
孩子兄弟表示法:
#include <iostream>
#include <set>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 26
struct node
{
int c;
int son,bro;
bool isWord;
}trie[150000];
int idx;
char word[10010][N];
set <string> st;
set <string>::iterator it;
void update(char *str)
{
int len = (int)strlen(str);
int p = 0;
for(int i=0; i<len; i++)
{
if(trie[p].son == 0)
{
trie[++idx].c = str[i]-'a';
trie[idx].son = trie[idx].bro = 0;
trie[idx].isWord = false;
trie[p].son = idx;
p = idx;
}
else
{
p = trie[p].son;
while(trie[p].c != str[i]-'a' && trie[p].bro)
p = trie[p].bro;
if(trie[p].c != str[i]-'a')
{
trie[++idx].c = str[i]-'a';
trie[idx].son = trie[idx].bro = 0;
trie[idx].isWord = false;
trie[p].bro = idx;
p = idx;
}
}
}
trie[p].isWord = true;
}
bool search(char *str)
{
int len = (int)strlen(str);
int p = trie[0].son;
for(int i=0; i<len; i++)
{
while(trie[p].c != str[i]-'a' && trie[p].bro)
p = trie[p].bro;
if(trie[p].c != str[i]-'a')
return false;
if(i + 1 == len)
break;
if(trie[p].son)
p = trie[p].son;
else
return false;
}
return trie[p].isWord;
}
int main()
{
trie[0].son = trie[0].bro = 0;
trie[0].isWord = false;
idx = 0;
char w[N];
int tot = 0;
while(scanf("%s",w))
{
if(strcmp(w,"#") == 0)
break;
update(w);
++tot;
strcpy(word[tot],w);
}
while(scanf("%s",w))
{
if(strcmp(w,"#") == 0)
break;
if(search(w))
printf("%s is correct\n",w);
else
{
st.clear();
int len = (int)strlen(w);
char ww[N];
int id;
for(int i=0; i<len; i++) //delete a letter
{
id = 0;
for(int k=0; k<len; k++)
{
if(k == i)continue;
ww[id++] = w[k];
}
ww[id] = '\0';
if(search(ww))
st.insert(ww);
}
for(int i=0; i<len; i++) // replace a letter
{
strcpy(ww,w);
for(int k=0; k<N; k++)
{
ww[i] = k+'a';
ww[len] = '\0';
if(search(ww))
st.insert(ww);
}
}
for(int i=0; i<=len; i++) // add a letter
{
for(int k=0; k<i; k++)
ww[k] = w[k];
for(int k=i+1; k<=len; k++)
ww[k] = w[k-1];
for(int k=0; k<N; k++)
{
ww[i] = k+'a';
ww[len+1] = '\0';
if(search(ww))
st.insert(ww);
}
}
printf("%s: ",w);
if(st.empty())
{
puts("");
continue;
}
for(int i=1; i<=tot; i++)
{
it = st.find(word[i]);
if(it != st.end())
{
cout << *it;
if(!st.empty()) printf(" ");
}
if(st.empty())
break;
}
puts("");
}
}
return 0;
}