您的位置:首页 > 其它

HDU1247 Hat’s Words(Trie树)

2016-01-26 20:40 351 查看
常规做法是枚举每个字符串每个位置,时间复杂度O(n*len*len),(建字典树O(n*len))。

然而我看这题第一眼想的是时间复杂度O(n*len)的算法。。就是建正反两棵字典树,每个字符串跑分别跑正反一遍字典树,再看看正反跑的结果能不能拼成原串。

然而常数太大了点,并没什么卵用。。

#include<cstdio>
#include<cstring>
using namespace std;
#define MAXL 22
#define MAXN 50100

int ch0[MAXN*MAXL][26],tn0,ch1[MAXN*MAXL][26],tn1;
bool flag[2][MAXN*MAXL];
void insert(char *s){
int x=0,len=strlen(s);
for(int i=0; i<len; ++i){
int y=s[i]-'a';
if(ch0[x][y]==0) ch0[x][y]=++tn0;
x=ch0[x][y];
}
flag[0][x]=1;
x=0;
for(int i=len-1; i>=0; --i){
int y=s[i]-'a';
if(ch1[x][y]==0) ch1[x][y]=++tn1;
x=ch1[x][y];
}
flag[1][x]=1;
}

char path[MAXL];
bool vis[2][MAXL];
void query(int len){
memset(vis,0,sizeof(vis));
int x=0;
for(int i=0; i<len; ++i){
int y=path[i]-'a';
if(ch0[x][y]==0) break;
x=ch0[x][y];
if(flag[0][x]) vis[0][i]=1;
}
x=0;
for(int i=len-1; i>=0; --i){
int y=path[i]-'a';
if(ch1[x][y]==0) break;
x=ch1[x][y];
if(flag[1][x]) vis[1][i]=1;
}
}
void dfs(int x,int k){
if(flag[0][x]){
query(k);
bool ishat=0;
for(int i=1; i<k; ++i){
if(vis[0][i-1] && vis[1][i]){
ishat=1;
break;
}
}
if(ishat){
for(int i=0; i<k; ++i) putchar(path[i]);
putchar('\n');
}
}
for(int i=0; i<26; ++i){
if(ch0[x][i]){
path[k]=i+'a';
dfs(ch0[x][i],k+1);
}
}
}
int main(){
char str[MAXL];
while(~scanf("%s",str)) insert(str);
dfs(0,0);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: