HDU 1671 Trie POJ 3630

HDU 1671

题意:给出N个串,问如果所有串都不是别的串的前缀串,则输出YES,否则输出NO。

算法:裸的Trie树,直接构建一个N串的Trie树,然后每次对该串进行匹配,如果匹配结果大于1,那么该串必定为2个串以上的前缀,那么就输出NO。

这道题唯一需要主要的就是要释放内存,不然会MLE。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) ( x << 1 )
#define RR(x) ( x << 1 | 1 )
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
using namespace std;

struct Trie{
    Trie *next[11] ;
    int count ;
    Trie(){
        mem(next ,0) ;
        count = 0 ;
    }
} ;
Trie *root = 0 ;
void build(char *a){
    int l = strlen(a) ;
    Trie *p = root ;
    for (int i = 0 ; i < l ;i ++ ){
        int tt = a[i] - '0' ;
        if(p -> next[tt] == 0){
            p -> next[tt] = new Trie() ;
        }
        p = p -> next[tt] ;
        p -> count ++ ;
    }
}

int search(char *a){
    int l = strlen(a) ;
    Trie *p = root ;
    for (int i = 0 ; i < l ; i ++ ){
        int tt = a[i] - '0' ;
        if(p -> next[tt] == 0){
            break ;
        }
        p = p -> next[tt] ;
    }
    if(p -> count > 1)return 1 ;
    else return 0 ;
}
char a[10006][111] ;

void deleteAll(Trie *p){
    for (int i = 0 ; i < 10 ;i ++ ){
        if(p -> next[i] != 0){
            deleteAll(p -> next[i]) ;
        }
    }
    delete p ;
}
int main() {
    int T ;
    cin >> T ;
    while( T -- ){
        int n ;
        root = new Trie() ;
        cin >> n ;
        for (int i = 0 ; i < n ;i ++ ){
            scanf("%s",a[i]) ;
            build(a[i]) ;
        }
        bool flag = 0 ;
        for (int i = 0 ;i < n ; i ++ ){
            if(search(a[i])){
                flag = 1 ;
                puts("NO") ;
                break ;
            }
        }
        if(!flag)puts("YES") ;
        deleteAll(root) ;
    }
    return 0 ;
}

POJ 3630

这两道题是一样的,但是HDU目测数据比较水,我用指针写可以过,但是POJ就T了,然后改成数组的写法才过。

以后还是都写数组的吧。指针还是太耗时了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) ( x << 1 )
#define RR(x) ( x << 1 | 1 )
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
using namespace std;

struct T{
    int next[11] ;
    int count ;
    T(){
        mem(next ,0) ;
        count = 0 ;
    }
} TT[111111] ;
int num = 0 ;
void build(char *a){
    int l = strlen(a) ;
    int p = 0 ;
    for (int i = 0 ; i < l ;i ++ ){
        int tt = a[i] - '0' ;
        if(TT[p].next[tt] == 0){
            TT[p].next[tt] = ++ num ;
        }
        p = TT[p].next[tt] ;
        TT[p].count ++ ;
    }
}
int search(char *a){
    int p = 0 ;
    int l = strlen(a) ;
    for (int i = 0 ; i < l ;i ++ ){
        int tt = a[i] - '0' ;
        if(TT[p].next[tt] == 0)break ;
        p = TT[p].next[tt] ;
    }
    if(TT[p].count > 1)return 1 ;
    return 0;
}

char a[10006][111] ;

int main() {
    int T ;
    cin >> T ;
    while( T -- ){
        int n ;
        num = 0 ;
        for (int i = 0 ;i < 111111 ;i ++ ){
            mem(TT[i].next ,0) ;
            TT[i].count = 0 ;
        }
        cin >> n ;
        for (int i = 0 ; i < n ;i ++ ){
            scanf("%s",a[i]) ;
            build(a[i]) ;
        }
        bool flag = 0 ;
        for (int i = 0 ;i < n ; i ++ ){
            if(search(a[i])){
                flag = 1 ;
                puts("NO") ;
                break ;
            }
        }
        if(!flag)puts("YES") ;
    }
    return 0 ;
}


你可能感兴趣的:(HDU 1671 Trie POJ 3630)