PKU 2774 Long Long Message 解题报告

来源:互联网 发布:ubuntu windows10 编辑:程序博客网 时间:2024/06/12 00:18
 具体的解题思路可以参考下面罗列的网址。
  1. /*
  2.   Title: Long Long Message
  3.   Author: Jeff
  4.   Time:  2008/10/21
  5.   Complexity: O(N*log(N));
  6.   Result: 5944K 1094MS/ AC
  7.   Reference: 
  8.         http://imlazy.ycool.com/post.2011818.html
  9.         http://imlazy.ycool.com/post.2011825.html
  10.         http://chencb.ycool.com/post.1901840.html
  11.         http://203.208.39.99/search?q=cache:zQ9R83uI7hoJ:jgshining.cn/blog/post/suffix_array_implemention.php+%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%89%8D%E7%BC%80&hl=zh-CN&newwindow=1&gl=cn&st_usg=ALhdy2_b5qju9mjFwiOWprnZP-4EhzPliw&strip=1
  12.   Description: 
  13.         求两个串的最长公共子串 
  14.   Tips:
  15.         LCP问题,后缀数组。 
  16.   p.s. 
  17. */
  18. #include <cstdio>
  19. #include <cstring>
  20. #include <algorithm>
  21. using namespace std;
  22. const int MAX = 100000;
  23. struct Sfx{
  24.     int idx;    //保存原始的下标 
  25.     int key[2]; //双关键字,k前缀意义下和2k前缀意义下 
  26.     bool operator<(const Sfx &other)const{  //用于排序 
  27.         return (key[0] < other.key[0]) || 
  28.             (key[0] == other.key[0] && key[1] < other.key[1]);    
  29.     }
  30. };
  31. Sfx tempSfx[2][MAX * 2 + 2];    //[0]用于存放SA结果,[1]用于中间变量 
  32. int buf[MAX * 2 + 2];           //用于存放rank[]; 
  33. char strText[MAX * 2 + 2];      //原始字符串 
  34. int H[MAX * 2 + 2];             //H数组 
  35. int ans;
  36. //计数排序 O(n) 
  37. void cSort(Sfx *in, int len, int key, Sfx *out){
  38.     memset(H, 0, sizeof(H));
  39.     int *cnt = H;
  40.     for(int i = 0; i < len; i++)
  41.         cnt[ in[i].key[key] ]++;
  42.     for(int i = 1; i < len; i++)
  43.         cnt[i] += cnt[i - 1];
  44.     for(int i = len - 1; i >= 0; i--)
  45.         out[ --cnt[in[i].key[key]] ] = in[i];
  46. }
  47. void buildSaf(char *text, int len){
  48.     Sfx *pTmp = tempSfx[1], *pSA = tempSfx[0];
  49.     int *rank = buf;
  50.     //初始化 
  51.     for(int i = 0; i < len; i++){
  52.         pSA[i].idx = pSA[i].key[1] = i;
  53.         pSA[i].key[0] = text[i];    
  54.     }
  55.     sort(pSA, pSA + len);
  56.     
  57.     for(int i = 0; i < len; i++)pSA[i].key[1] = 0;
  58.     
  59.     //log(n)次操作 
  60.     int wid = 1;
  61.     while(wid < len){
  62.         //计算rank值 
  63.         rank[pSA[0].idx] = 0;
  64.         for(int i = 1; i < len; i++){
  65.             rank[pSA[i].idx] = rank[pSA[i-1].idx];
  66.             if(pSA[i-1] < pSA[i])
  67.                 rank[pSA[i].idx]++;
  68.         }
  69.         //赋值关键字 
  70.         for(int i = 0; i < len; i++){
  71.             pSA[i].idx = i;
  72.             pSA[i].key[0] = rank[i];
  73.             pSA[i].key[1] = (i + wid < len ? rank[i+wid] : 0);
  74.         }
  75.         
  76.         cSort(pSA, len, 1, pTmp); cSort(pTmp, len, 0, pSA); //对双关键字进行计数排序 
  77.         wid *= 2;
  78.     }
  79. }
  80. //计算H数组 
  81. void calculateH(char *text, int len1, int len2){
  82.     int *rank = buf;
  83.     Sfx *pSA = tempSfx[0];
  84.     for(int i = 0; i < len1 + len2; i++){
  85.         if(rank[i] == 0)
  86.             H[i] = 0;
  87.         else
  88.             int k, j;
  89.             if(i == 0 || H[i - 1] < 1){
  90.                 k = 0;            
  91.             }else{
  92.                 k = H[i-1] - 1;    
  93.             }
  94.             for(j = pSA[ rank[i]-1 ].idx; text[j + k] == text[i + k]; k++);
  95.             H[i] = k;
  96.             //求出结果 
  97.             if(i < len1 && j >= len1 || i >= len1 && j < len1)
  98.                 if(ans < H[i])
  99.                     ans = H[i];
  100.         }
  101.     }    
  102. }
  103. int main(){
  104.     freopen("in.txt""r", stdin);
  105.     freopen("out.txt""w", stdout);
  106.     while(scanf("%s", strText) != EOF){
  107.         ans = 0;
  108.         int len1 = strlen(strText);
  109.         scanf("%s", strText + len1);
  110.         int len2 = strlen(strText) - len1;
  111.         buildSaf(strText, len1 + len2);
  112.         calculateH(strText, len1, len2);
  113.         Sfx *pSA = tempSfx[0];
  114.         /*for(int i = 0; i < len1 + len2; i++)
  115.             printf("%d ", pSA[i].idx);
  116.         printf("/n");
  117.         for(int i = 0; i < len1 + len2; i++)
  118.             printf("%d ", buf[i]);
  119.         printf("/n");
  120.         for(int i = 0; i < len1 + len2; i++)
  121.             printf("%d ", H[i]);
  122.         printf("/n");*/
  123.         printf("%d/n", ans);
  124.     }    
  125.     return 0;    
  126. }