POJ 1056 and POJ 3630

来源:互联网 发布:软件著作权作品说明书 编辑:程序博客网 时间:2024/06/04 22:40

POJ 3630

这道题目是个典型的字典树题目,不断的数字串,并判断是不是有前缀出现,需要注意的是:由于输入的串不一定会按长度排序,所以如果某个数字串的前缀出现在该数字串的后面,那么就会出现错误。我们可以这样,对输入的串进行排序,不过这样太麻烦了。考虑一下即使某个串在其子串前先出现,它还是会沿着子串的路径走,当子串出现的时候,我们可以这样判断:当数字串全部插入进去的时候,我们判断是不是有其它子串走过这条路,如果有,那么必然出现重复的情况,这样我们也就很容易的得出正确的答案。

#include<iostream>#include<string.h>#include<stdio.h>using namespace std ;#define MAXN 4000000struct Trie{    int next[10] ;    int cnt ;}trie[MAXN];void initTrie(Trie &t){    for(int i = 0 ; i < 10 ; i++)        t.next[i] = 0 ;    t.cnt = 0 ;}char readl[15] ;int ncount ;int order  ;void init(){    for(int i = 0 ; i <= ncount ; i ++){        initTrie(trie[i]) ;    }    ncount = 0 ;    order = 0 ;}int insert(char * a , int nx){    if( *a ){        if(trie[nx].cnt != 0){            if(trie[nx].next[*a - '0'] == 0){                trie[nx].next[*a - '0'] = ++ncount ;            }            insert(a + 1 , trie[nx].next[*a - '0'] ) ;            return trie[nx].cnt ;        }        else{            if(trie[nx].next[*a - '0'] == 0){                trie[nx].next[*a - '0'] = ++ncount ;            }            return insert(a + 1 , trie[nx].next[*a - '0'] ) ;        }    }    else{        if(trie[nx].cnt != 0)            return trie[nx].cnt ;        trie[nx].cnt = ++ order ;        //注意当字符串为排序的时候,短的在后插入的时候,要判断当前的路是否有其它字符串走过        for(int i = 0 ; i <= 9 ; i ++){            if(trie[nx].next[i] != 0){                return 1 ;            }        }        return 0 ;    }}int main(){    int t ;    int n ;    scanf("%d" , &t) ;    while(t--){        scanf("%d" , &n) ;        init() ;        int flag = 0 ;        for(;n--;){            scanf("%s" , readl) ;            if(!flag){                flag = insert(readl , 0) ;            }        }        if(flag){            printf("NO\n") ;        }        else{            printf("YES\n") ;        }    }    return 0 ;}

POJ1056这道题目于上面的类似,不过这道题目比上面的要容易的多,不需要考虑数字串的长度问题,数据也弱的多。改一下上面的输入输出格式,就可以过这个题了。


原创粉丝点击