zoukankan      html  css  js  c++  java
  • 蓝书2.3 Trie字典树

    T1 IMMEDIATE DECODABILITY poj 1056

    题目大意:

    一些数字串 求是否存在一个串是另一个串的前缀

    思路:

    对于所有串经过的点权+1 如果一个点的end被访问过或经过一个被标记为end的点 就存在

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #include<set>
    10 #define inf 2139062143
    11 #define ll long long
    12 #define MAXN 15100
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,tr[100][2],T,ans,vis[MAXN],sz,end[MAXN];
    22 char ch[15];
    23 void ins(char *c,int len)
    24 {
    25     int pos=0;
    26     for(int i=0;i<len;i++)
    27     {
    28         if(!tr[pos][c[i]-'0']) tr[pos][c[i]-'0']=++sz;
    29         pos=tr[pos][c[i]-'0'],vis[pos]++;
    30         if(end[pos]) ans=1;
    31     }
    32     if(vis[pos]>1) ans=1;end[pos]=1;
    33 }
    34 int main()
    35 {
    36     while(scanf("%s",ch)!=EOF)
    37     {
    38         ans=sz=0;memset(vis,0,sizeof(vis));
    39         memset(tr,0,sizeof(tr));memset(end,0,sizeof(end));
    40         while(ch[0]!='9'){ins(ch,strlen(ch));scanf("%s",ch);}
    41         if(!ans) printf("Set %d is immediately decodable
    ",++T);
    42         else printf("Set %d is not immediately decodable
    ",++T);
    43     }
    44 }
    View Code

    T2 L语言 bzoj 1212

    题目大意:

    给字典 求一个字符串能被字典解释的最长前缀

    思路:

    因为字典内的单词都很短

    可以对每一个模式串的位置向后匹配递推

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #include<set>
    10 #define inf 2139062143
    11 #define ll long long
    12 #define MAXN 1000100
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,tr[220][30],sz,end[MAXN],f[MAXN];
    22 char ch[15],s[MAXN];
    23 void ins(char *c,int len)
    24 {
    25     int pos=0;
    26     for(int i=0;i<len;i++)
    27     {
    28         if(!tr[pos][c[i]-'a']) tr[pos][c[i]-'a']=++sz;
    29         pos=tr[pos][c[i]-'a'];
    30     }
    31     end[pos]=1;
    32 }
    33 int query(char *c,int len)
    34 {
    35     int pos=0,res=0,k;
    36     if(tr[pos][c[0]-'a']) f[0]=1;
    37     else return 0;
    38     for(int i=0;i<len;i++)
    39     {
    40         if(!f[i]) continue;
    41         pos=tr[pos][c[i]-'a'],k=0;
    42         while(pos)
    43         {
    44             if(end[pos]) f[i+k+1]=1,res=max(res,min(i+k+1,len));
    45             pos=tr[pos][c[i+k+1]-'a'],k++;
    46         }
    47     }
    48     return res;
    49 }
    50 int main()
    51 {
    52     n=read(),m=read();
    53     for(int i=1;i<=n;i++) {scanf("%s",ch);ins(ch,strlen(ch));}
    54     while(m--)
    55     {
    56         scanf("%s",s);memset(f,0,sizeof(f));
    57         printf("%d
    ",query(s,strlen(s)));
    58     }
    59 }
    View Code

    T3 秘密信息 bzoj 1590

    题目大意:

    n个信息 m个密码 对每个密码求有多少信息与它匹配 也就是说,有多少信息和这条密码有着相同的前缀

    思路:

    加到字典序里记一下经过的end标记和这个密码的end位置有多少个信息经过

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #include<set>
    10 #define inf 2139062143
    11 #define ll long long
    12 #define MAXN 500100
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,tr[MAXN][2],sz,end[MAXN],s[MAXN];
    22 void ins(int len)
    23 {
    24     int pos=0;
    25     for(int i=0,k;i<len;i++)
    26     {
    27         k=read();
    28         if(!tr[pos][k]) tr[pos][k]=++sz;
    29         pos=tr[pos][k],s[pos]++;
    30     }
    31     end[pos]++;
    32 }
    33 int query(int len)
    34 {
    35     int pos=0,res=0,f=0;
    36     for(int i=0,k;i<len;i++)
    37     {
    38         k=read();
    39         if(f) continue;pos=tr[pos][k];
    40         if(!pos) f=1;
    41         if(i!=len-1) res+=end[pos];
    42     }
    43     if(!f) res+=s[pos];
    44     return res;
    45 }
    46 int main()
    47 {
    48     n=read(),m=read();int k;
    49     for(int i=1;i<=n;i++) {k=read();ins(k);}
    50     while(m--) {k=read();printf("%d
    ",query(k));}
    51 }
    View Code

    T4 背单词 bzoj 4567

    题目大意:

    放n个单词,放每个单词之前如果没有把这个单词的后缀都先放上去则代价为n*n)

    每个单词的代价等于这个单词的位置减去上一个出现的这个单词的后缀的位置(若没有后缀则代价为它的位置)

    求最少的代价

    思路:

    首先肯定要把所有单词的后缀都加入否则代价太大

    然后倒着把单词加入建trie树 对于所有end节点向上最近的end连边

    可以得到一个树 每个树按照size从小到大遍历 

    答案就是所有节点的序号-父亲的序号

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #include<set>
    10 #define inf 2139062143
    11 #define ll long long
    12 #define MAXN 500100
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,tr[MAXN][30],tot,end[MAXN],st[MAXN],top;
    22 ll ans;
    23 char ch[MAXN],s[MAXN];
    24 int fst[MAXN],nxt[MAXN],to[MAXN],cnt,fa[MAXN],sz[MAXN];
    25 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
    26 void ins(char *c,int len)
    27 {
    28     int pos=0,tmp=0;
    29     for(int i=len-1;i>=0;i--)
    30     {
    31         if(!tr[pos][c[i]-'a']) tr[pos][c[i]-'a']=++tot;
    32         pos=tr[pos][c[i]-'a'];
    33     }
    34     end[pos]=1;
    35 }
    36 void dfs(int x,int anc)
    37 {
    38     if(end[x]) {add(x,anc);add(anc,x);fa[x]=anc,anc=x;}
    39     for(int i=0;i<26;i++)
    40         if(tr[x][i]) dfs(tr[x][i],anc);
    41 }
    42 void build(int x)
    43 {
    44     sz[x]=1;
    45     for(int i=fst[x];i;i=nxt[i]) 
    46         if(to[i]!=fa[x]) {build(to[i]);sz[x]+=sz[to[i]];}
    47 }
    48 bool cmp(int x,int y) {return sz[x]<sz[y];} 
    49 void dfs(int x)
    50 {
    51     int l=top+1,r;ll s=1;
    52     for(int i=fst[x];i;i=nxt[i]) if(to[i]!=fa[x])st[++top]=to[i];
    53     sort(st+l,st+top+1,cmp);r=top;
    54     for(int i=l;i<=r;i++) {ans+=s,s+=sz[st[i]];dfs(st[i]);}
    55 }
    56 int main()
    57 {
    58     n=read();
    59     for(int i=1;i<=n;i++) {scanf("%s",ch);ins(ch,strlen(ch));}
    60     dfs(0,0);build(0);dfs(0);printf("%lld
    ",ans);
    61 }
    View Code

    T5 The xor-longest Path bzoj 1954 

    题解链接  唯一的区别是poj 从0开始

  • 相关阅读:
    白话经典算法系列之中的一个 冒泡排序的三种实现
    Spring3.0 AOP 具体解释
    Android中Preference的使用以及监听事件分析
    Java中的匿名内部类
    【剑指offer】二叉树中和为某一值的路径
    Haskell 差点儿无痛苦上手指南
    Oracle Minus 取差集
    Windows Mobile 6.0 SDK和中文模拟器下载
    caffe源代码分析--math_functions.cu代码研究
    代码阅读分析工具Understand 2.0试用
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9335186.html
Copyright © 2011-2022 走看看