hdu1247 两棵Trie
hdu1247 Hat’s Words
传送门
题意
判断单词表中的一个单词是否为两个单词表中的两个其他单词串联的形式,输出所有这样的单词
题解
建立两棵Trie,一棵是正序,一棵是倒序
遍历所有单词,设立一个标记数组,每个单词首先在正序的Trie中查找,判断每个前缀的位置是否是其他单词,在标记数组的对应下标处打上标记,之后在倒序Trie中查找,在标记数组中\((n-i-2)\)的位置处打上标记。最后遍历标记数组,如果某个位置的值等于\(2\),说明这个单词这一位置的前后缀都在单词表中出现过,符合条件
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<climits>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=100010;
string s[50010];
int tot1,tot2,trie1[maxn][30],trie2[maxn][30];
int sum[50010],len[maxn];
bool terminal1[maxn],terminal2[maxn];
void insert1(string ss,int n){
int root=0;
for(int i=0;i<n;i++){
int id=ss[i]-'a';
if(!trie1[root][id]) trie1[root][id]=++tot1;
root=trie1[root][id];
}
terminal1[root]=true;
}
void insert2(string ss,int n){
int root=0;
for(int i=0;i<n;i++){
int id=ss[i]-'a';
if(!trie2[root][id]) trie2[root][id]=++tot2;
root=trie2[root][id];
}
terminal2[root]=true;
}
void find1(string ss,int n){
int root=0;
for(int i=0;i<n-1;i++){
int id=ss[i]-'a';
root=trie1[root][id];
if(terminal1[root]) sum[i]++;
}
}
void find2(string ss,int n){
int root=0;
for(int i=0;i<n-1;i++){
int id=ss[i]-'a';
root=trie2[root][id];
if(terminal2[root]) sum[n-i-2]++;
}
}
int main(){
std::ios::sync_with_stdio(false);
int m=0;
while(cin>>s[m]){
len[m]=s[m].length();
insert1(s[m],len[m]);
reverse(s[m].begin(),s[m].end());
insert2(s[m],len[m]);
m++;
}
for(int i=0;i<m;i++){
for(int j=0;j<len[i];j++) sum[j]=0;
find2(s[i],len[i]);
reverse(s[i].begin(),s[i].end());
find1(s[i],len[i]);
bool f=false;
for(int j=0;j<len[i];j++){
if(sum[j]==2){
f=true;
break;
}
}
if(f) cout<<s[i]<<"\n";
}
return 0;
}