• SYSU-7, Gym 100273J, trie+hash


    cnm毛子的题是正宗内家拳法啊orz(捶地),拼的就是智商,这题我们队想了老半天后缀自动机,掏出各种黑科技无果

    题目大意:构建一个自动机可以表达给定的n个串,询问最小的自动机节点树为多少。

    解:最裸的自动机其实就是一棵trie,那么我们考虑优化这棵trie,考虑拓扑排序倒过来做,可以发现其实如果两个节点如果他们指向的节点状态完全一致,那么这两个节点是等价的,所以我们不断合并这些节点即可。但是拓扑可能会慢,而且貌似会退化n方(没细想),但一般地,我们用dfs出栈序去做这个hash去重即可。

    cnm居然hash冲突orz。。。。早知道就不hash成一个值而是学2队 所有儿子状态弄成一个结构丢进map里算了。如果赛场上这样写wa了根本调不出来,就要背大锅了。

      1 #include <cstdio>
      2 #include <string>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <cstring>
      7 #include <complex>
      8 #include <set>
      9 #include <vector>
     10 #include <map>
     11 #include <queue>
     12 #include <deque>
     13 #include <ctime>
     14 
     15 using namespace std;
     16 
     17 const double EPS = 1e-8;
     18 
     19 #define ABS(x) ((x)<0?(-(x)):(x))
     20 #define SQR(x) ((x)*(x))
     21 #define MIN(a,b) ((a)<(b)?(a):(b))
     22 #define MAX(a,b) ((a)>(b)?(a):(b))
     23 
     24 #define LSON(x) ((x)<<1)
     25 #define RSON(x) (((x)<<1)+1)
     26 #define LOWBIT(x) ((x)&(-(x)))
     27 #define MAXS 1111
     28 #define MAXN 222222
     29 #define VOIDPOINT 0
     30 #define LL long long
     31 #define OO 214748364
     32 
     33 #define MAXT 11
     34 
     35 const LL MOD = 1e11+9;
     36 
     37 LL poww[111];
     38 
     39 struct node{
     40     node *ch[26];
     41     int lab, isWord;
     42     LL hash;
     43 };
     44 map <LL, node* > mp;
     45 
     46 struct TrieTree{
     47     node t[MAXN], *root;
     48     int cnt;
     49     node* newNode() {
     50         node *u = &t[++cnt];
     51         memset(u, 0, sizeof(t[0]));
     52         u->lab = cnt;
     53         return u;
     54     }
     55     void clear() {
     56         root = &t[0];
     57         cnt = 0; memset(t, 0, sizeof(t[0]));
     58     }
     59     void insert(const char *str) {
     60         int len = strlen(str);
     61         node *u = root;
     62         for (int i = 0; i < len; ++i) {
     63             if (u->ch[str[i] - 'a'] == 0) {
     64                 u->ch[str[i] - 'a'] = newNode();
     65             }
     66             u = u->ch[str[i] - 'a'];
     67         }
     68         u->isWord = 1;
     69     }
     70 } Trie;
     71 
     72 void dfs(node *&u) {
     73     LL res = 0;
     74     for (int i = 0; i < 26; ++i) {
     75         if (u->ch[i]) {
     76             dfs(u->ch[i]);
     77         } 
     78         res = (res * (1LL << 22) + (u->ch[i] ? u->ch[i]->lab : MAXN+1)) % MOD;
     79     }
     80 //    cout << u->lab << ' '<< res << endl;
     81 //    for (int i = 0; i < 26; ++i) 
     82 //        cout << (u->ch[i] ? u->ch[i]->lab : -1) << ' '; cout << endl;
     83     res = (res * 2 + u->isWord) % MOD;
     84     u->hash = res;
     85     if (mp.count(u->hash) == 0) {
     86         mp[u->hash] = u;    
     87     } else 
     88         u = mp[u->hash];
     89 }
     90 
     91 char str[MAXS];
     92 
     93 int main() {
     94     freopen("test.txt", "r", stdin);
     95 //    freopen("language.in", "r", stdin);    freopen("language.out", "w", stdout);
     96 
     97     Trie.clear();
     98     int n;
     99     scanf("%d", &n);
    100     for (int i = 0; i < n; ++i) {
    101         scanf("%s", str);
    102         Trie.insert(str);
    103     }
    104 
    105     mp.clear();
    106     dfs(Trie.root);
    107 
    108     cout << mp.size() << endl;
    109 
    110     fclose(stdin);
    111     fclose(stdout);
    112     return 0;
    113 }
    Gym 100273J
  • 相关阅读:
    Leetcode1716. 计算力扣银行的钱
    Leetcode 575. 分糖果(可以,一次过)
    Lesson9——Pandas iteration遍历
    Lesson10——Pandas sorting排序
    Lesson8——Pandas reindex重置索引
    NumPy 教程目录
    Lesson3——NumPy 数据类型
    Lesson6——NumPy 数组操作
    Lesson5——NumPy 创建数组
    Lesson1——NumPy NumPy 安装
  • 原文地址:https://www.cnblogs.com/wmzisfoolish/p/5651833.html
Copyright © 2020-2023  润新知