• [Ahoi2013]差异


      后缀数组+单调栈

      代码

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 using namespace std;
      5 const int N = 501000;
      6 
      7 const int MAXN =  N;      
      8 
      9 struct SuffixArray{
     10     int wa[MAXN];          
     11     int wb[MAXN];            
     12     int wv[MAXN];           
     13     int ws[MAXN];          
     14 
     15     int sa[MAXN];           
     16     int rank[MAXN];        
     17     int height[MAXN];      
     18     int r[MAXN];            
     19     int n;           
     20     int m;                 
     21 
     22     void input(int *val, int len, int Max){
     23         for (int i = 0;i < len;i++)
     24             r[i] = val[i];
     25         r[len] = 0;                      
     26         n = len;
     27         m = Max;
     28         calSa();
     29         calHeight();
     30     }
     31 
     32     int cmp(int *r, int a, int b, int l){
     33         return (r[a] == r[b] && r[a + l] == r[b + l]);
     34     }
     35 
     36     void calSa(){                 
     37         int i, j, p, *x = wa, *y = wb, *t;
     38         for (i = 0;i < m;i++) ws[i] = 0;
     39         for (i = 0;i < n + 1;i++) ws[x[i] = r[i]]++;
     40         for (i = 1;i < m;i++) ws[i] += ws[i - 1];
     41         for (i = n;i >= 0;i--) sa[--ws[x[i]]] = i;
     42         for (j = 1, p = 1;p < n + 1;j *= 2, m = p){
     43             for (p = 0, i = n - j + 1;i < n + 1;i++) y[p++] = i;
     44             for (i = 0;i < n + 1;i++) if (sa[i] >= j) y[p++] = sa[i] - j;
     45             for (i = 0;i < n + 1;i++) wv[i] = x[y[i]];
     46             for (i = 0;i < m;i++) ws[i] = 0;
     47             for (i = 0;i < n + 1;i++) ws[wv[i]]++;
     48             for (i = 1;i < m;i++) ws[i] += ws[i - 1];
     49             for (i = n;i >= 0;i--) sa[--ws[wv[i]]] = y[i];
     50             for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n + 1;i++)
     51                 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
     52         }
     53     }
     54 
     55     void calHeight(){              
     56         int i, j, k = 0;
     57         for (i = 1;i <= n;i++) rank[sa[i]] = i;
     58         for (i = 0;i < n;height[rank[i++]] = k)
     59             for (k?k--:0, j = sa[rank[i]- 1];r[i + k] == r[j + k];k++);
     60     }
     61    
     62     int Log[MAXN];
     63     int best[20][MAXN];
     64     void initRMQ() {            
     65         Log[0] = -1;
     66         for(int i = 1;i <= MAXN;i++){
     67             Log[i]=(i & (i - 1))?Log[i - 1] : Log[i - 1] + 1 ;
     68         }
     69         for(int i = 1; i <= n ; i ++) best[0][i] = height[i];
     70         for(int i = 1; i <= Log[n] ; i ++) {
     71             int limit = n - (1<<i) + 1;
     72             for(int j = 1; j <= limit ; j ++) {
     73                 best[i][j] = (best[i-1][j] > best[i-1][j+(1<<i>>1)]) ? best[i-1][j+(1<<i>>1)] : best[i-1][j];
     74             }
     75         }
     76     }
     77     int lcp(int a,int b) {      
     78         a = rank[a];    b = rank[b];
     79         if(a > b){
     80             int t = a;
     81             a = b;
     82             b = t;
     83         }
     84         a ++;
     85         int t = Log[b - a + 1];
     86         return (best[t][a] > best[t][b - (1<<t) + 1])? best[t][b - (1<<t) + 1] : best[t][a];
     87     }
     88 }SA;
     89 int a[N],i,len,top,stack[N];
     90 long long ans,sum;
     91 char s[N];
     92 int main()
     93 {
     94     scanf("%s",&s);
     95     len=strlen(s);
     96     for (i=1;i<=len;i++)
     97     {
     98         ans=ans+(long long)i*(len-1);
     99         a[i-1]=s[i-1];
    100     }
    101     SA.input(a,len,200);
    102     for (i=1;i<=len;i++)
    103     {
    104         while (SA.height[i]<SA.height[stack[top]])
    105         {
    106             sum=sum-(long long)(stack[top]-stack[top-1])*SA.height[stack[top]];
    107             top--;
    108         }
    109         top++;stack[top]=i;
    110         sum=sum+(long long)(stack[top]-stack[top-1])*SA.height[stack[top]];
    111         ans=ans-2*sum;
    112     }
    113     printf("%lld
    ",ans);
    114 }
    115 //3 1 4 2 5 0
  • 相关阅读:
    使用servicename连接Oracle数据库
    使用SID连接Oracle数据库
    使用xlrd模块
    【Project Euler 8】Largest product in a series
    Git使用帮助
    【Project Euler 1】Multiples of 3 and 5
    VSCode使用新体验
    导出牛顿引力形式为平方反比的两种方式
    NOIP2018游记
    即将退役声明
  • 原文地址:https://www.cnblogs.com/fzmh/p/5522046.html
Copyright © 2020-2023  润新知