zoukankan      html  css  js  c++  java
  • 【BZOJ 2746】旅行问题

    Description

    yz是Z国的领导人,他规定每个地区的名字只能为26个小写拉丁字母的一个。由于地 区数有可能超过26个,便产生了一个问题,如何辨别名字相同的地区?于是yz规定,一个 地区的描述必须包含它的所有上级,且上级按次序排列。于是,一个地区的描述是一个字符 串。比如说,一个地区的名字为c,它的上级为b,b的上级为a,a没有上级,那么这个地 区就描述为abc。显然,这个描述同时包含了c的上级b和b的上级a的描述,分别为ab和a。 值得注意的是,每个地区最多有一个上级,同一上级的地区之间名字不同,没有上级的 地区之间名字不同。现在,yz对外公布了n个地区的描述,这些描述中包含了Z国所有地区的描述,并让 你处理来访者的旅行问题。现有m对人访问这个国家,对于每对人,第一个人喜欢第i个描述中的第j个地区,设 这个地区描述为s1,第二个人喜欢第k个描述中的第l个地区,设这个地区描述为s2。他们为了统一行程,决定访问描述为s的地区(显然他们只关心地区的名字,并非是地区本身), 设s的长度为t,s需要满足以下条件: 
    1:t<=j, t<=l; 
    1:s[1..t] = s1[j-t+1 … j], s[1..t] = s2[l-t+1 … l];(即s为s1中1到k位 与s2中1到l位的公共后缀) 
    2:t最大化。 
    为了不使输出过大,你只需把这个字符串按照如下生成的26进制数转成10进制后mod 1000000007后输出: 
    a->0 
    b->1 



    z->25 
    比如地区cab被编码成2 *    26? + 0 * 26? + 1 * 26? = 1353。 

    Input

    第一行给定一个整数n 
    第2…n+1行:每i+1行给定一个字符串a[i],表示第i个描述。 
    接下来一行一个整数m 
    接下来m行:每行给定四个整数i,j,k,l,字母含义与题目描述一致。 

    Output


    共m行,每行一个整数,表示答案字符串的编码。 

    Sample Input

    2
    aabb babb
    2
    1 3 2 3
    1 4 2 4

    Sample Output

    1
    1
    【样例说明】
    询问1中的公共后缀有ab和b,但是没有ab这个地区,只有b地区,所以只能选择b这个 地区;
    询问2中的公共后缀有abb、bb和b,但是没有abb和bb这两个地区,只有b地区,所以 只能选择b这个地区。

    HINT

    【数据范围】


     设这个国家地区总数数为tot(注意:输入的字符串总长度可能超过tot!) 对于30%的数据,满足tot,m,n<=100; 

    对于50%的数据,满足tot,m,n<=1000; 

    对于80%的数据,满足tot,m,n<=100000; 

    对于100%的数据,满足tot,m,n<=1000000; 

    保证输入文件不超过20MB。 

     
    分析:
      要求找出两个字符串的公共后缀满足这个后缀又是某一个字符串的前缀。
      用AC自动机解决,根据Fail指针的性质(指向最长的一个后缀满足它是某一个串的前缀)作LCA就好了。
     
    代码:
      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 #ifdef Lightning
      5 #define NOTHING() printf ("33[0m")
      6 #define RED() printf ("33[31m")
      7 #define PURPLE() printf ("33[35m")
      8 #define BLUE() printf ("33[34m")
      9 #define GREEN() printf ("33[32m")
     10 #endif
     11 
     12 struct Trie
     13 {
     14     long long key;
     15     int next[27], fail, frmq[23], fd;
     16 } trie[1000010];
     17 
     18 int n, m;
     19 int sta[1000010], city[2000010], num;
     20 int len, prev, size, now;
     21 int p1, p2, p3, p4;
     22 int que[1000010], head, rear;
     23 char str[1000010];
     24 
     25 inline int new_node (int ch, int father)
     26 {
     27     size++;
     28     trie[father].next[ch] = size;
     29     trie[size].key = (trie[father].key * 26 + ch) % 1000000007;
     30     return size;
     31 }
     32 
     33 void bfs ()
     34 {
     35     int node;
     36     for (que[head = rear = 0] = 0; head <= rear; head++)
     37     {
     38         node = que[head];
     39         for (int i = 0; i < 26; i++)
     40         {
     41             if (node) trie[node].fd = trie[trie[node].fail].fd + 1;
     42             else trie[node].fd = 0;
     43             if (trie[node].next[i])
     44             {
     45                 if (node) trie[trie[node].next[i]].fail = trie[trie[node].fail].next[i];
     46                 que[++rear] = trie[node].next[i];
     47             }else trie[node].next[i] = trie[trie[node].fail].next[i];
     48         }
     49     }
     50 }
     51 
     52 void frmq_build ()
     53 {
     54     for (int i = 1; i <= size; i++)
     55         trie[i].frmq[0] = trie[i].fail;
     56     for (int k = 0; k < 22; k++)
     57         for (int i = 1; i <= size; i++)
     58             trie[i].frmq[k + 1] = trie[trie[i].frmq[k]].frmq[k];
     59 }
     60 
     61 int lca (int e1, int e2)
     62 {
     63     if (trie[e1].fd > trie[e2].fd)
     64         e1 ^= e2, e2 ^= e1, e1 ^= e2;
     65     #ifdef Lightning
     66         GREEN ();
     67         printf ("DEPTH : %d %d
    ", trie[e1].fd, trie[e2].fd);
     68         NOTHING ();
     69     #endif
     70     for (int i = 22; i >= 0; i--)
     71         if (trie[trie[e2].frmq[i]].fd >= trie[e1].fd)
     72             e2 = trie[e2].frmq[i];
     73     if (e1 == e2) return e1;
     74     #ifdef Lightning
     75         if (trie[e1].fd != trie[e2].fd)
     76         {
     77             RED ();
     78             printf ("
    Wrong!!!
    ");
     79             printf ("%d %d
    
    ", trie[e1].fd, trie[e2].fd);
     80             NOTHING ();
     81         }
     82     #endif
     83     for (int i = 22; i >= 0; i--)
     84         if (trie[e1].frmq[i] != trie[e2].frmq[i])
     85             e1 = trie[e1].frmq[i], e2 = trie[e2].frmq[i];
     86     return trie[e1].frmq[0];
     87 }
     88 
     89 int main ()
     90 {
     91     #ifdef Lightning
     92         BLUE ();
     93         printf ("How many descriptions?
     - ");
     94         NOTHING ();
     95     #endif
     96     scanf ("%d", &n);
     97     size = 0;
     98     for (int i = 1; i <= n; i++)
     99     {
    100         #ifdef Lightning
    101             BLUE ();
    102             printf ("Description %d - ", i);
    103             NOTHING ();
    104         #endif
    105         scanf ("%s", str);
    106         len = strlen (str);
    107         prev = 0;
    108         sta[i] = num;
    109         #ifdef Lightning
    110             BLUE ();
    111             printf ("Index : %d   Start : %d
    ", i, sta[i]);
    112             NOTHING ();
    113         #endif
    114         for (int j = 0; j < len; j++)
    115         {
    116             now = trie[prev].next[str[j] - 'a'];
    117             if (!now) now = new_node (str[j] - 'a', prev);
    118             num++;
    119             city[num] = prev = now;
    120         }
    121     }
    122     #ifdef Lightning
    123         GREEN ();
    124         printf ("Checking...
    The Size : %d
    ", size);
    125         printf ("Aho-Corasick Automation Building...
    ");
    126     #endif
    127     bfs ();
    128     #ifdef Lightning
    129         printf ("Done...
    ");
    130         printf ("RMQ Building...
    ");
    131     #endif
    132     frmq_build ();
    133     #ifdef Lightning
    134         BLUE ();
    135         printf ("How many couples are there?
     - ");
    136         NOTHING ();
    137     #endif
    138     scanf ("%d", &m);
    139     for (int i = 1, node = 0; i <= m; i++)
    140     {
    141         #ifdef Lightning
    142             BLUE ();
    143             printf ("Couple %d - ", i);
    144             NOTHING ();
    145         #endif
    146         scanf ("%d %d %d %d", &p1, &p2, &p3, &p4);
    147         #ifdef Lightning
    148             BLUE ();
    149             printf ("Input : %d %d %d %d
    ", p1, p2, p3, p4);
    150             GREEN ();
    151             printf ("Working...
    ");
    152             NOTHING ();
    153         #endif
    154         #ifdef Lightning
    155             BLUE ();
    156             printf ("City 1 : %d   City 2 : %d
    ", sta[p1] + p2, sta[p3] + p4);
    157             NOTHING ();
    158         #endif
    159         node = lca (city[sta[p1] + p2], city[sta[p3] + p4]);
    160         #ifdef Lightning
    161             GREEN ();
    162             printf ("The LCA : %d      ", node);
    163             printf ("The Answer : ");
    164             NOTHING ();
    165         #endif
    166         printf ("%lld
    ", trie[node].key);
    167     }
    168 }

    PS:调试信息什么的不用管。。。

  • 相关阅读:
    十步完全理解 SQL
    Oracle VM Virtual
    Pycharm 使用
    Open Yale course:Listening to Music
    SQL 必知必会
    安装 SQL server 2008 R2
    Ubuntu安装mysql之后,编译找不到头文件
    core dump文件的生成
    Linux静态库与动态库制作过程
    GEC6818连接Ubuntu,下载程序至开发板
  • 原文地址:https://www.cnblogs.com/lightning34/p/4448499.html
Copyright © 2011-2022 走看看