HDU 1247 字典树

建立两个字典树,一个按照前缀储存,一个按照后缀储存。
查找时就把要查找的字符串的正串和反串分别放到两个树里跑``,用两个数组记录到哪里可以找到对应的前缀(f)与后缀(e),然后扫一遍即可。

#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <queue>
#include <map>
#define N 500000
using namespace std;
const int INF = 0x3f3f3f3f;
struct Node{
    Node* ch[26];
    bool flag;
};
bool f[30],e[30];
char s1[30],s2[30];
char s[N][30];
struct Tree{
    Node a[N];
    int p;
    Node* root;
    Node* newNode(){
        p++;
        memset(a[p].ch,0,sizeof(a[p].ch));
        a[p].flag = 0;
        return &a[p];
    }
    Tree(){
        p = 0;
        root = newNode();
    }
    void insert(char s[]){
        Node* cur = root;
        while (*s != '\0')
        {
            int x = *s - 'a';
            if(cur->ch[x] == NULL){
                cur->ch[x] = newNode();
            }
            cur = cur->ch[x];
            s++;
        }
        cur->flag = 1;
    }

    void check(char s[],bool t[]){
        Node* cur= root;
        int cnt = -1;
        while (*s != '\0')
        {
            if(cur->flag){
                t[cnt] = 1;
            }
            int x = *s - 'a';
            if(cur->ch[x] == NULL){
                return;
            }
            cnt++;
            cur = cur->ch[x];
            s++;
        }
    }
};

Tree zheng,fan;

void turn(){
    int len = strlen(s1);
    for(int i=0;i<len;i++){
        s2[i] = s1[len-1-i];
    }
    s2[len] = '\0';
}

bool check(){
    memset(f,0,sizeof(f));
    memset(e,0,sizeof(e));
    zheng.check(s1,f);
    fan.check(s2,e);
    int len = strlen(s1);
    for(int i=0;i < len-1;i++){
        if(f[i] && e[len-2-i]){
            return 1;
        }
    }
    return 0;
}

int main(){
    int i = -1;
    while (gets(s1) && s1[0] != '\0')
    {
        i++;
        zheng.insert(s1);
        turn();
        fan.insert(s2);
        strcpy(s[i],s1);
    }
    for(int j=0;j<=i;j++){
        strcpy(s1,s[j]);
        turn();
        if(check()){
            printf("%s\n",s1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值