zoukankan      html  css  js  c++  java
  • Uva 12361 File Retrieval 后缀数组+并查集

    题意:有F个单词,1 <= F <=60 , 长度<=10^4, 每次可以输入一个字符串,所有包含该字串的单词会形成一个集合。

    问最多能形成多少个不同的集合。集合不能为空。

    分析:用后缀数组处理。然后首先考虑一个单词形成一个集合的情况,若该单词是其他单词的字串,则该单词显然不会形成一个集合,那么利用后缀数组,

    对于每个单词看能否与其他单词有LCP,且LCP 长度为该单词本身长度。

    然后就是多个单词形成集合的情况:比较简单的处理方式就是将h数组值相同的下标集中存储,比如h[x] = h[y] = h[z] = 5, 那么将x,y,z存到h

    值对应为5的数组中,然后按照h值,假设为v,从大到小的顺序,将所有h值为v的下标与其周围的LCP大于v的(h[v-1],h[v])对应的子串,更新并查集。实际意义就是,每次将h值为h[v]的一些子串所在的单词合并到之前h值> h[v]的子串所在的单词形成的并查集中,得到的并查集中单词一定有长度>=h[v]公共字串,这样的并查集实际就是一个合法的单词集合,可以利用二进制表示,每次得到新的集合则将二进制表示加入到统计集合的set中,最后结果就是set的大小。

    AC代码其实是比赛时写的,当时多个单词部分不是上面这种写法,不过类似。

      1 #include <bits/stdc++.h>
      2 #define  in  freopen("solve_in.txt", "r", stdin);
      3 #define  bug(x)  printf("Line %d:>>>>>>>
    ", (x));
      4 
      5 #define  REV(a)    reverse((a).begin(), (a).end())
      6 #define  READ(a, n) {REP(i, n) cin>>(a)[i];}
      7 #define  REP(i, n) for(int i = 0; i < (n); i++)
      8 #define  VREP(i, n, base) for(int i = (n); i >= (base); i--)
      9 #define  Rep(i, base, n) for(int i = (base); i < (n); i++)
     10 #define  REPS(s, i) for(int i = 0; (s)[i]; i++)
     11 using namespace std;
     12 typedef unsigned long long ULL;
     13 typedef long long LL;
     14 typedef map<ULL, int> UMps;
     15 set<ULL> se;
     16 
     17 const int maxn = 10500 + 100;
     18 const int maxm = 66;
     19 const int maxlen = maxn*maxm+100;
     20 int s[maxlen];
     21 int sa[maxlen], t[maxlen], t2[maxlen], c[maxlen], n, m, dp[maxlen][30];
     22 int num[maxlen];
     23 LL ans;
     24 void build_sa(int m) {
     25     int *x = t, *y = t2;
     26 
     27     REP(i, m) c[i] = 0;
     28     REP(i, n) c[x[i] = s[i]]++;
     29     Rep(i, 1, m) c[i] += c[i-1];
     30     VREP(i, n-1, 0) sa[--c[x[i]]] = i;
     31 
     32     for(int k = 1; k <= n; k <<= 1) {
     33         int p = 0;
     34 
     35         Rep(i, n-k, n) y[p++] = i;
     36         REP(i, n) if(sa[i] >= k) y[p++] = sa[i]-k;
     37 
     38         REP(i, m) c[i] = 0;
     39         REP(i, n) c[x[y[i]]]++;
     40         Rep(i, 1, m) c[i] += c[i-1];
     41 
     42         VREP(i, n-1, 0) sa[--c[x[y[i]]]] = y[i];
     43         swap(x, y);
     44         p = 1, x[sa[0]] = 0;
     45         Rep(i, 1, n)
     46         x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
     47         if(p >= n) break;
     48         m = p;
     49     }
     50 }
     51 int rk[maxlen], h[maxlen];
     52 
     53 void getHeight() {
     54     int j, k = 0;
     55     h[0] = 0;
     56     REP(i, n) rk[sa[i]] = i;
     57     REP(i, n) {
     58         if(k) k--;
     59         if(rk[i] == 0)
     60             continue;
     61         j = sa[rk[i]-1];
     62         while( s[i+k] == s[j+k]) k++;
     63         h[rk[i]] = k;
     64     }
     65 }
     66 void RMQ_init() {
     67     REP(i, n) dp[i][0] = h[i];
     68     for(int k = 1; (1<<k) <= n; k++)
     69         for(int i = 0; i + (1<<k) <= n; i++)
     70             dp[i][k] = min(dp[i][k-1], dp[i+(1<<(k-1))][k-1]);
     71 }
     72 int RMQ(int l, int r) {
     73     int k = 0;
     74     while((1<<(k+1)) <= r-l+1) k++;
     75     return min(dp[l][k], dp[r-(1<<k)+1][k]);
     76 }
     77 char word[maxm][maxn];
     78 int nn;
     79 inline int idx(char ch) {
     80     return ch-'a'+1;
     81 }
     82 int vis[70], slen[70];
     83 
     84 void solveSingle() {
     85     se.clear();
     86     memset(vis, 0, sizeof vis);
     87     for(int i = 1; i < n; i++){
     88         if(h[i]){
     89             if(num[sa[i]] != -1 && h[i] == slen[num[sa[i]]])
     90                 vis[num[sa[i]]] = 1;
     91             if(num[sa[i-1]] != -1 && h[i] == slen[num[sa[i-1]]])
     92                 vis[num[sa[i-1]]] = 1;
     93         }
     94     }
     95     for(int i = 0; i < nn; i++) if(!vis[i])
     96             se.insert(1ULL<<i);
     97 }
     98 void dfs(int l, int r, int now) {
     99     if(l >= r)
    100         return;
    101     ULL tmp;
    102 
    103     for(int i = l; i < r; ) {
    104         tmp = 0;
    105         while(i < r && h[i] <= now)
    106             i++;
    107         if(i >= r)
    108             break;
    109         int mx = (int)1e9;
    110         int j = i;
    111         mx = min(mx, h[j]);
    112         if(j < r && num[sa[j-1]] != -1)
    113             tmp |= 1ULL<<num[sa[j-1]];
    114         while(j < r && h[j] > now) {
    115             mx = min(mx, h[j]);
    116             if(num[sa[j]] != -1)
    117                 tmp |= 1ULL<<num[sa[j]];
    118             j++;
    119         }
    120         if(tmp)
    121         se.insert(tmp);
    122         dfs(i, j, mx);
    123         i = j;
    124     }
    125 }
    126 void solve() {
    127     build_sa(120);
    128     getHeight();
    129     solveSingle();
    130     ULL tmp;
    131     for(int i = 1; i < n; ) {
    132         int mx = (int)1e9;
    133         tmp = 0;
    134         while(i < n && !h[i])
    135             i++;
    136         if(i >= n)
    137             break;
    138         mx = min(mx, h[i]);
    139         int j = i;
    140         if(j < n && num[sa[j-1]] != -1)
    141             tmp |= 1ULL<<num[sa[j-1]];
    142         while(j < n && h[j]) {
    143             mx = min(mx, h[j]);
    144             if(num[sa[j]] != -1)
    145                 tmp |= 1ULL<<num[sa[j]];
    146             j++;
    147         }
    148         if(tmp)
    149         se.insert(tmp);
    150         dfs(i, j, mx);
    151         i = j;
    152     }
    153     printf("%llu
    ", (ULL)se.size());
    154 }
    155 int main() {
    156 
    157 
    158     while(scanf("%d", &nn), nn) {
    159         n = 0;
    160         memset(num, -1, sizeof num);
    161         for(int i = 0; i < nn; i++) {
    162             slen[i] = 0;
    163             scanf("%s", word[i]);
    164             for(int j = 0; word[i][j]; j++) {
    165                 slen[i]++;
    166                 s[n] = idx(word[i][j]);
    167                 num[n++] = i;
    168             }
    169             s[n++] = 30+i;
    170         }
    171         s[n-1] = 0;
    172         solve();
    173     }
    174     return 0;
    175 }
    View Code
  • 相关阅读:
    loadrunner数据库MySQL参数化列表乱码问题
    [MySQL]导入导出
    [MySQL]命令行工具和基本操作
    [MySQL]安装和启动
    win7下loadrunner创建mysql数据库参数化问题解决
    Win7-64bit系统下安装mysql的ODBC驱动
    loadrunner个版本历程
    性能分析与调优的原理
    性能分析与调优的原理
    loadrunner解决“服务器正在运行中”方法
  • 原文地址:https://www.cnblogs.com/rootial/p/3940638.html
Copyright © 2011-2022 走看看