zoukankan      html  css  js  c++  java
  • Tire树,hdu2846,hdu4825

    hdu4825                      hdu2846

    放一张图来解释tire树的构成(u1s1个人感觉像是hash表)

    查询有多少前缀相同字符串的模板

     1 int cnt = 1;
     2 int g[26 * maxn][26], vis[26 * maxn], v[26 * maxn];
     3 il void add(char *w,int id){
     4     int p = 0, l = strlen(w);
     5     for (int i = 0; i < l; i++){
     6         int c = w[i] - 'a';
     7         if (!g[p][c]){
     8             g[p][c] = cnt++;
     9         }
    10         vis[g[p][c]]++;
    11         p = g[p][c];
    12     }
    13 }
    14 il int query(char *w){
    15     int p = 0, l = strlen(w);
    16     for (int i = 0; i < l; i++){
    17         int c = w[i] - 'a';
    18         if (!g[p][c]){
    19             return 0;
    20         }
    21         p = g[p][c];
    22     }
    23     return vis[p];
    24 }

    hdu4825

    题意:

    给长度为n的数组Ki(1<=i<=n),再输入m个S,在集合当中找出一个正整数 Ki ,使得 Ki 与 S 的异或结果最大

    样例输入                                 输出:

    2                                             Case #1:
    3 2                                          4
    3 4 5                                       3
    1                                             Case #2:
    5                                             4
    4 1
    4 6 5 6
    3
     

    思路:

    字典树把每个数用二进制从高位到低位保存,因为高位影响较大。

    寻找与S每个位都不一样的数字,但是如果哪一位没有不一样的,那只能找一样的了

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    const int maxn=1e5+10;
    ll g[maxn*32][2],cnt, m, n, a;
    ll vis[maxn*32];
    il void add(ll n){
        ll p=0;
        for (it i = 32; i >= 0; i--){
            int c = (n >> i) & 1;
            if (!g[p][c]){
                g[p][c]=cnt++;
            }
            p = g[p][c];
        }
        vis[p] = n;
    }
    il void query(ll n){
        ll p = 0;
        for (it i = 32; i >= 0; i--){
            int c = 1 - (n >> i) & 1;
            if (!g[p][c]){
                c = 1 - c;
            }
            p = g[p][c];
        }
        printf("%lld
    ", vis[p]);
    }
    int main(){
        int c=1, t;
        scanf("%lld",&t);
        while (t--){
            cnt= 1;
            mem(vis, 0);mem(g, 0);
            scanf("%lld%lld",&n,&m);
            for (it i = 0; i < n; i++){
                scanf("%lld",&a);
                add(a);
            }
            printf("Case #%d:
    ",c++);
            for (it i = 0; i < m; i++){
                scanf("%lld",&a);
                query(a);
            }
        }
        return 0;
    }

    hdu2846

    题意:

    给n个字符串,再给m个字符串S,问S在n个字符串中是其子串

    样例输入                                   输出

    2                                                2

    adad

    dadd

    1

    ad

    思路:

    tire树,边存字符串边记录cnt出现几次。因为他要子串,所以长度较小所以可以直接暴力o(n^2),把每个子串存进去

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    const int maxn=1e5+10;
    char s[30];
    int k = 1, n, m;
    int g[26 * maxn][26], vis[26 * maxn], v[26 * maxn];
    il void add(char *w,int id){
        int p = 0, l = strlen(w);
        for (it i = 0; i < l; i++){
            int c = w[i] - 'a';
            if (!g[p][c]){
                g[p][c] = k++;
                vis[g[p][c]]++;
                v[g[p][c]] = id;
            }
            p = g[p][c];
            if (v[p] != id){
                vis[p]++;
                v[p] = id;
            }
        }
    }
    il int query(char *w){
        int p = 0, l = strlen(w);
        for (it i = 0; i < l; i++){
            int c = w[i] - 'a';
            if (!g[p][c]){
                return 0;
            }
            p = g[p][c];
        }
        return vis[p];
    }
    int main(){
        scanf("%d",&n);
        for (it i = 0; i < n; i++){
            scanf("%s",&s);
            int l = strlen(s);
            for (it j = 0; j < l; j++){
                add(s + j, i);
            }
        }
        scanf("%d",&m);
        for (it i = 0; i < m; i++){
            scanf("%s",&s);
            printf("%d
    ",query(s));
        }
        return 0;
    }
  • 相关阅读:
    C# learn note
    深入研究Servlet线程安全性问题
    SQL Server中的临时表和表变量
    jQuery笔记
    使用ScriptX控件进行Web打印
    asp.net MVC 设置页面否编译
    Javascript闭包【转载】
    几种开源协议
    扩展IIS7支持的文件类型(转)
    VS2012关闭烦人的文件预览选项卡
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/12462605.html
Copyright © 2011-2022 走看看