cf861D 字典树+时间戳

好久没碰字典树之类的题了,搞起来有点生疏

/*
把所有母串的后缀加入字典树中 
然后再扫一次所有母串的后缀,把后缀放到字典树中查询,找到第一个访问次数为1的结点返回即可 
num在计数时,同一个母串的子串只能增加一次,所以用一个时间戳time数组来标记一下 
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 100000
char strs[maxn][20];
int n,t;
struct Trie{
    int nxt[maxn*10][11],num[maxn*11],time[maxn*11];
    int root,L;
    int newnode(){
        for(int i=0;i<10;i++)nxt[L][i]=-1;
        num[L]=0,time[L]=0;
        return L++; 
    }
    void init(){
        L=0;root=newnode();
    }
    void insert(char buf[]){
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++){
            if(nxt[now][buf[i]-'0']==-1)
                nxt[now][buf[i]-'0']=newnode();
            now=nxt[now][buf[i]-'0'];
            if(time[now]!=t)
                num[now]++,time[now]=t;
        }
    }
    int query(char buf[]){
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++){
            now=nxt[now][buf[i]-'0'];
            if(num[now]==1)return i;
        }
        return -1;
    }
}tr;
int main(){
    int i;
    cin>>n;
    tr.init();
    for(i=1;i<=n;i++){
        t=i;
        cin>>strs[i];
        for(int j=0;j<10;j++){
            char tmp[100]={};
            strcpy(tmp,strs[i]+j);
            tr.insert(tmp);
        }
    }
    
    for(i=1;i<=n;i++){
        int l=0,r=0,Min=999;
        for(int j=0;j<10;j++){
            char buf[100]={};
            strcpy(buf,strs[i]+j);
            int tmp=tr.query(buf);
            if(tmp==-1)continue;
            else {
                if(Min>tmp){
                    Min=tmp;
                    l=j,r=j+tmp;
                }
            }
        }
        for(int k=l;k<=r;k++)
            printf("%c",strs[i][k]);
        puts("");
    
    }
}
原文地址:https://www.cnblogs.com/zsben991126/p/10346816.html