zoukankan      html  css  js  c++  java
  • 分块和后缀数组的模板

      好久没写博客了。北京区域赛前先把模板往博客上储存一下,以免以后忘记了。

      分块的话在vjudge上搜索:备战区域赛-数据结构分块-キリト

      后缀数组的话搜索kuangbin的后缀数组即可。

     1 int n,m;
     2 //num分块的个数
     3 //belong[i]表示i属于哪一块
     4 //block表示块的大小
     5 //l[i]表示i这块的左端点位置
     6 //r[i]表示右端点位置
     7 int block,num,l[N],r[N],belong[N];
     8 int build()
     9 {
    10     block = (int)sqrt(1.0*n);
    11     num = n / block;if(n%block) num++;
    12     for(int i=1;i<=num;i++) l[i] = (i-1)*block+1, r[i] = i*block;
    13     r[num] = n;
    14     for(int i=1;i<=n;i++) belong[i] = (i-1)/block + 1;
    15 }
    分块
     1 /*下面的代码用来解决两个比较长的字符串的最长公共子串的长度:中间插个未出现的字符,再连接后进行构造即可。*/
     2 #include <stdio.h>
     3 #include <algorithm>
     4 #include <string.h>
     5 using namespace std;
     6 const int N = 100000*2 + 100;
     7 typedef long long ll;
     8 
     9 /**
    10  *    sa[i]:表示排在第i位的后缀的起始下标
    11  *    rank[i]:表示后缀suffix(i)排在第几
    12  *    height[i]:sa[i-1] 与 sa[i]的LCP(最长公共前缀)值
    13  *
    14  * */
    15  /*
    16     如果整数的话模板改成int.
    17     加一个数a[n] = 0 。 这样他的排名是第一个。
    18     construct(a,n+1);
    19 
    20     字符串的话。
    21     len = strlen(str);
    22     construct(s,strlen(s)+1);
    23     排名第0的是个空字符串。
    24 
    25     height[i]:sa[i-1] 与 sa[i]的LCP(最长公共前缀)值
    26     所以height[1] = 0;
    27     rank[len] = 0;
    28     sa[0] = len;
    29  */
    30 int sa[N],rnk[N],height[N];
    31 void construct(const char *s,int n,int m = 256) {
    32     static int t1[N],t2[N],c[N];
    33     int *x = t1,*y = t2;
    34     int i,j,k,p,l;
    35     for (i = 0; i < m; ++ i) c[i] = 0;
    36     for (i = 0; i < n; ++ i) c[x[i] = s[i]] ++;
    37     for (i = 1; i < m; ++ i) c[i] += c[i - 1];
    38     for (i = n - 1; i >= 0; -- i) sa[--c[x[i]]] = i;
    39     for (k = 1; k <= n; k <<= 1) {
    40         p = 0;
    41         for (i = n - k; i < n; ++ i) y[p++] = i;
    42         for (i = 0; i < n; ++ i) if (sa[i] >= k) y[p++] = sa[i] - k;
    43         for (i = 0; i < m; ++ i) c[i] = 0;
    44         for (i = 0; i < n; ++ i) c[x[y[i]]] ++;
    45         for (i = 1; i < m; ++ i) c[i] += c[i - 1];
    46         for (i = n - 1; i >= 0; -- i) sa[--c[x[y[i]]]] = y[i];
    47         std::swap(x,y);
    48         p = 1; x[sa[0]] = 0;
    49         for (i = 1; i < n; ++ i)
    50             x[sa[i]] = y[sa[i - 1]] == y[sa[i]]
    51                 && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1: p ++;
    52         if (p >= n) break;
    53         m = p;
    54     }
    55     for (i = 0; i < n; ++ i) rnk[sa[i]] = i;
    56     for (i = 0,l = 0; i < n; ++ i) {
    57         if (rnk[i]) {
    58             j = sa[rnk[i] - 1];
    59             while (s[i + l] == s[j + l]) l++;
    60             height[rnk[i]] = l;
    61             if (l) l--;
    62         }
    63     }
    64 }
    65 
    66 int T;
    67 char s[N],s2[N];
    68 
    69 int main()
    70 {
    71     while(scanf("%s",s+1)==1)
    72     {
    73         scanf("%s",s2+1);
    74         int len = strlen(s+1);
    75         int temp = len;
    76         s[len+1] = '$';
    77         for(int i=len+2,now=1;s2[now];i++,now++)
    78         {
    79             s[i] = s2[now];
    80             if(s2[now+1] == 0) {s[i+1] = 0;len=i;}
    81         }
    82         
    83         construct(s,len+1);
    84         int ans = 0;
    85         for(int i=2;i<=len;i++)
    86         {
    87             int a = min(sa[i-1],sa[i]);
    88             int b = max(sa[i-1],sa[i]);
    89             if(a<=temp && b>temp+1) ans = max(ans,height[i]);
    90         }
    91         printf("%d
    ",ans);
    92     }
    93     return 0;
    94 }
    后缀数组
  • 相关阅读:
    WCF异常管理—不要在using语句中调用WCF服务(z)
    正则表达式
    nginx汇总(z)
    WCF编解码实现
    zTree -- jQuery 树插件
    C# 程序异常管理方案
    WPF剪切板问题-OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
    乘法逆元
    二叉树后序遍历(非递归)
    P1892 [BOI2003]团伙
  • 原文地址:https://www.cnblogs.com/zzyDS/p/6051039.html
Copyright © 2011-2022 走看看