zoukankan      html  css  js  c++  java
  • 2016集训测试赛(十九)Problem C: 无聊的字符串

    Description

    Solution

    傻X题
    我的方法是建立后缀后缀树, 然后在DFS序列上直接二分即可.
    关键在于如何得到后缀树上每个字符对应的字节点: 我们要在后缀自动机上记录每个点在后缀树上对应的字母. 考虑如何实现, 我们在后缀自动机上的每个状态上, 记录其所对应的在字符串中的位置, 减去其父亲节点的长度即可得到每个节点对应的后缀树上的字符.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
     
    using namespace std;
    const int LEN = (int)2e5;
    struct suffixAutomaton
    {
       int tp, rt, L, R;
       struct node
       {
           int suc[26], pre;
           int endPosition, len, c;
           int vst;
           int successorOnSuffixTree[26];
           inline node() {memset(suc, -1, sizeof(suc)); pre = -1; vst = 0; memset(successorOnSuffixTree, -1, sizeof(successorOnSuffixTree));}
       }nd[LEN << 1];
       void DFS(int u)
       {
           nd[u].vst = 1; if(u != rt) nd[nd[u].pre].successorOnSuffixTree[nd[u].c] = u;
           for(int i = 0; i < 26; ++ i) if(~ nd[u].suc[i] && ! nd[nd[u].suc[i]].vst) DFS(nd[u].suc[i]);
       }
       int clk;
       int idx[LEN << 1], sz[LEN << 1];
       long long sum[LEN << 1];
       inline void getId(int u)
       {
           int cur = clk ++;
           idx[cur] = u; sz[cur] = u == rt ? 0 : nd[u].len - nd[nd[u].pre].len;
           for(int i = 0; i < 26; ++ i) if(~ nd[u].successorOnSuffixTree[i])
           {
               int v = nd[u].successorOnSuffixTree[i];
               getId(v);
               if(nd[u].endPosition == -1 || nd[u].endPosition > nd[v].endPosition) nd[u].endPosition = nd[v].endPosition;
           }
       }
       inline void build(char *str, int len)
       {
           L = R = 0;
           rt = 0; nd[rt].len = 0; tp = 1;
           int lst = rt;
           for(int i = len - 1; ~ i; -- i)
           {
               char c = str[i] - 'a';
               int u = tp ++; nd[u].len = nd[lst].len + 1; nd[u].endPosition = i;
               for(; ~ lst && nd[lst].suc[c] == -1; lst = nd[lst].pre) nd[lst].suc[c] = u;
               if(lst == -1) nd[u].pre = rt, nd[u].c = str[i] - 'a';
               else
               {
                   int p = nd[lst].suc[c];
                   if(nd[p].len == nd[lst].len + 1) nd[u].pre = p, nd[u].c = str[i + nd[p].len] - 'a';
                   else
                   {
                       int q = tp ++;
                       memcpy(nd[q].suc, nd[p].suc, sizeof(nd[p].suc)); nd[q].pre = nd[p].pre; nd[q].len = nd[lst].len + 1; nd[q].endPosition = i;
                       // we must set nd[q].endPosition's value right now, 'cause it may be used later
                       nd[q].c = str[i + nd[nd[q].pre].len] - 'a';
                       nd[p].pre = nd[u].pre = q;
                       nd[p].c = str[nd[p].endPosition + nd[q].len] - 'a'; nd[u].c = str[i + nd[q].len] - 'a';
                       for(; ~ lst && nd[lst].suc[c] == p; lst = nd[lst].pre) nd[lst].suc[c] = q;
                   }
               }
               lst = u;
           }
           DFS(rt);
           clk = 0; getId(rt);
           sum[0] = sz[0]; for(int i = 1; i < tp; ++ i) sum[i] = sum[i - 1] + sz[i];
       }
       inline void query(long long k)
       {
           k = (long long)(L ^ R ^ k) + 1;
           // int k = v;
           int curL = 0, curR = tp - 1, pos = -1;
           while(curL <= curR)
           {
               int mid = curL + curR >> 1;
               if(sum[mid] >= k) {pos = mid; curR = mid - 1;} else curL = mid + 1;
           }
           if(pos == -1) {L = 0; R = 0; printf("%d %d
    ", L, R); return;}
           L = nd[idx[pos]].endPosition + 1; R = L + (k - sum[pos - 1] + nd[nd[idx[pos]].pre].len) - 1;
           printf("%d %d
    ", L, R);
       }
    }SAM;
    int main()
    {
     
    #ifndef ONLINE_JUDGE
     
       freopen("string.in", "r", stdin);
       freopen("string.out", "w", stdout);
     
    #endif
     
       static char str[LEN]; scanf("%s", str);
       SAM.build(str, strlen(str));
       int m; scanf("%d", &m);
       long long v;
       for(int i = 0; i < m; ++ i) scanf("%lld", &v), SAM.query(v);
    }
    
  • 相关阅读:
    android AsyncTask
    android利用provider查询同一个数据库中没有对外暴露出来的表
    PowerProfile.java与power_profile.xml
    Java的动态绑定机制
    Activity Intent Flags及Task相关属性
    非阻塞socket调用connect, epoll和select检查连接情况示例
    Linux Epoll相关知识
    JAVA并发编程
    Activity生命周期(深入理解)
    Android线程间通信更新UI的方法(重点分析EventBus)
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7490235.html
Copyright © 2011-2022 走看看