Tire 树 练习

poj 2001

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
typedef struct Tire{
    int v; //可以用来统计个数
    int id;
    int next[26];
};
int ptr=0;
Tire word[10005];

void init(int z){
    for(int i=0;i<26;i++)
        word[z].next[i]=-1,word[z].v=0;  //初始化为-1
}
void creatTire(char *str,int x){
    int len=strlen(str);
    int cnt=0;
    for(int i=0;i<len;i++){
         if(word[cnt].next[str[i]-'a']==-1){
             word[cnt].next[str[i]-'a']=++ptr;
             init(ptr);   // 相当于初始化新开的节点
             cnt=ptr;     // 相当于移位
         }
         else{
             cnt=word[cnt].next[str[i]-'a'];
//             word[cnt].v++   下面有进行++;
         }
         if(word[cnt].id!=x) {
             word[cnt].v++;
         }
         word[cnt].id=x;
//         printf("%d %d\n",ptr,cnt);
//         printf("%d %c %d\n",x,str[i],word[cnt].v);
    }
}
int findTire(char *str){
    int len=strlen(str);
    int cnt=0;
    for(int  i=0;i<len;i++){
        int id=str[i]-'a';
        cnt=word[cnt].next[id];
        if(word[cnt].v==1){
            return i;
        }
    }
    return -1;
//    return word[cnt].v; //查找串是字符串中的前缀
}
char str[10050][30];
int main(){
    int cnt=1;
    init(0);  // 我就知道你会忘了写
    freopen("1.txt","r",stdin);
    while(~scanf("%s",str[cnt])){
        cnt++;
    }
    for(int i=1;i<cnt;i++){
        creatTire(str[i],i);
    }
    for(int i=1;i<cnt;i++){
        printf("%s ",str[i]);
        int pos=findTire(str[i]);
        if(pos==-1)
            printf("%s\n",str[i]);
        else{
            for(int j=0;j<=pos;j++)
                printf("%c",str[i][j]);
            printf("\n");
        }
    }
    return 0;
}

poj3630=HDU1671

内存有点烦,试了好多次,最后开了500W 的数组,才过的;
poj上 // Tire 数组500Wac,开100Wre,开1000W ME
hdu 上限制内存了,但是我开100W的数组都可以 ac, 搞不懂??
还有就是 MD,又忘记写最开始的init(0),我真的是醉了

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
typedef struct Tire{
    int v; //可以用来统计个数
    int id;
    int next[12];
    int flag;
};
int ptr=0;
Tire word[5000005];  

void init(int z){
    for(int i=0;i<12;i++){
        word[z].next[i]=-1,word[z].v=0;  //初始化为-1
        word[z].flag=0;
    }
}
void creatTire(char *str,int x){
    int len=strlen(str);
    int cnt=0;
    for(int i=0;i<len;i++){
         if(word[cnt].next[str[i]-'0']==-1){
             word[cnt].next[str[i]-'0']=++ptr;
             init(ptr);   // 相当于初始化新开的节点
             cnt=ptr;     // 相当于移位
         }
         else{
             cnt=word[cnt].next[str[i]-'0'];
         }
         if(i==len-1){
//           printf("%d %d %d\n",i,x,cnt);
             word[cnt].flag=-1;
             word[cnt].id=x;
         }
    }
}
int findTire(char *str,int x){
    int len=strlen(str);
    int cnt=0;
    for(int  i=0;i<len;i++){
        int id=str[i]-'0';
        cnt=word[cnt].next[id];
//        printf("%c %d %d\n",str[i],word[cnt].flag,word[cnt].id);
        if(word[cnt].flag==-1 && word[cnt].id!=x){
            return 0;
        }
    }
    return 1;
//    return word[cnt].v; //查找串是字符串中的前缀
}
char str[10005][15];
int main(){
    //freopen("1.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--){
        init(0); //  大哥,我真是给你跪下了,你好歹记住写一次吧
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",str[i]);
            creatTire(str[i],i);
        }
        int flag=1;
        for(int i=1;i<=n;i++){
            flag=findTire(str[i],i);
            if(!flag){
                break;
            }
        }
        flag==1?printf("YES\n"):printf("NO\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值