Trie刷题

  • P3879 [TJOI2010]阅读理解
    虽然不需要用trie,但是秉着练习需要,就强行加上trie,没想到其中收获了stl的应用熟练度。首先想的是用set来存取在哪一行,但是可是要求加上结尾不换行,那么在遍历的时候我有很喜欢写for (auto it:se[p]),显然如果我判断it == se[p].end()是不正确的,因为it是int。如果判断it==*se[p].end()好像也不行,于是就写了for循环。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 9;
set<int> se[N];
struct AC {  
    int tr[N][27], idx = 0;
    string str;
    void insert(int x) {
        int p = 0;
        for (int i = 0; str[i]; i ++) {
            int id = str[i] - 'a';
            if (!tr[p][id])tr[p][id ] = ++ idx;
            p = tr[p][id];
        }
        se[p].insert(x);
    }
}T;
int main() {
    int n;
    cin >> n;
    for (int i =1 ; i <= n; i ++) {
        int cnt;cin >> cnt;
        while (cnt--) {
            cin >> T.str;
            T.insert(i);
        }
    }
    int m;cin >> m;
    for (int i = 1; i <= m; i ++) {
        cin >> T.str;
        int p = 0;
        bool f = 0;
        for (int j = 0; T.str[j]; j ++) {
            int id = T.str[j] - 'a';
            if (id < 0||id >= 26) {f = 1;break;}
            if (!T.tr[p][id]) {f = 1;break;}
            p = T.tr[p][id];
        }
        if (f||se[p].size() == 0) {cout << endl;continue;}
        auto cmp = se[p].end();
        cmp--;
        for (auto it = se[p].begin(); it != se[p].end();it++){
            if (it == cmp) {
                cout << *it <<"
";
            } else 
                cout << *it <<" ";
        }
    }
}
  • HDU6955 Xor sum多校1 .vj
    小思维就是求异或和大于等于k的最短区间。然后就是可以转化的是,异或前缀和,然后就可以把异或前缀和放入字典树,然后字典树上节点维护所能到达的最右边的位置,然后查询即可,困难在于实现。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e5 + 9;
const ll inf = 0x3f3f3f3f;
struct trie {
    ll tr[N *30][2], idx, r[N*30 ];
    void init() {
        // memset(r, -1, sizeof r);
        // memset(tr, 0, sizeof tr);
        for (int i = 0; i <= idx; i ++) {
            tr[i][0] = tr[i][1] = 0;
            r[i] = -1;
        }
        idx = 0;
    }
    void insert(ll x, ll pos){
        ll p = 0;
        bool f = 0;
        for (ll i = 32; i >= 0; i--) {
            ll id = (x >> i)&1;
            if (!tr[p][id])tr[p][id] = ++idx;
            p = tr[p][id];
            if (id == 1) f = 1;
            if (f)
            r[p] = pos;
        }
    }
    int ask(ll k,ll sum) {
        ll maxr1 = -1, maxr2 =-1;
        ll p = 0;
        bool f = 0;
        for (ll i = 32; i >=0; i --) {
            ll id1 = (k >> i) & 1;
            ll id2 = (sum >> (i)) & 1;
            if (id1 == 1) {
                //maxr1 = max(maxr1, r[tr[p][id2 ^ 1]]);
                p = tr[p][id2^1];
            } else {
                    maxr2 = max(maxr2, r[tr[p][id2 ^ 1]]);
                    //maxr1 = max(maxr1, r[tr[p][id2]]);
                p = tr[p][id2];
            }
            if (!p) return max(r[p], maxr2);
        }
        return max(r[p], maxr2);
    }
}T;
ll a[N];
ll sum[N];
void solve() {
    int n, k;
    T.init();
    scanf("%d%d", &n, &k);
    ll sum = 0;
    ll len = 9999999999999, ansl = 0, ansr = 0;
    for (int i = 1; i <=n; i++) {
        ll x;scanf("%lld", &x);
        sum ^= x;
        int pos = T.ask(k , sum);
        T.insert(sum, i);
        //cout << sum << " ";
        if (pos == -1)continue;
        if (i - pos + 1 <= 0)continue;
        if (len > i - pos+1) {len = i-pos + 1;ansl = pos, ansr = i;}
    }
    /*----------------------------------------------------------------
    3 2 1 3 7 7 4 1 0 
    */
    if (len <=0||(ansl ==ansr && ansr == 0)) puts("-1"); 
    else printf("%lld %lld
", ansl + 1 , ansr);
}
signed main() {
   // freopen("in.txt", "r", stdin);
   // freopen("out.out", "w", stdout);
    clock_t start_time=clock();
   ll t = 1;scanf("%lld", &t);
   while (t--) {
      solve();
   }
   clock_t end_time=clock();
   //cout<< "Running time is: "<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl;//输出运行时间
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/15168957.html