• 【POJ3415】Common Substrings(后缀数组,单调栈)


    题意:

    n<=1e5

    思路:

    我的做法和题解有些不同

    题解是维护A的单调栈算B的贡献,反过来再做一次

    我是去掉起始位置不同这个限制条件先算总方案数,再把两个串内部不合法的方案数减去

    式子展开之后是 sigma(lcp(i,j))-K*L*(L+1)/2+合法(i,j)对数,其中L为连续的height[i]>=K的区域长度

    sigma(lcp(i,j))计算部分与BZOJ3238类似

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<map>
      8 #include<set>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef unsigned int uint;
     14 typedef unsigned long long ull;
     15 typedef pair<int,int> PII;
     16 typedef vector<int> VI;
     17 #define fi first
     18 #define se second 
     19 #define MP make_pair
     20 #define N   210000
     21 #define MOD 1000000007
     22 #define eps 1e-8 
     23 #define pi acos(-1)
     24 #define oo  1000000000
     25 
     26 char a[N],b[N];
     27 int n,i,s[N],sa[N],wa[N],wb[N],wc[N],wd[N],height[N],rank[N],
     28     H[N],stk[N];
     29 ll ans,K,c[N],d[N];
     30 
     31 int read()
     32 { 
     33    int v=0,f=1;
     34    char c=getchar();
     35    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     36    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     37    return v*f;
     38 }
     39 
     40 bool cmp(int *r,int a,int b,int l)
     41 {
     42     return r[a]==r[b]&&r[a+l]==r[b+l];
     43 }
     44 
     45 void getsa(int *r,int *sa,int n,int m)
     46 {
     47     int *x=wa,*y=wb,j,p;
     48     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
     49     for(i=1;i<m;i++) wc[i]+=wc[i-1];
     50     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
     51     for(j=1,p=1;p<n;j*=2,m=p)
     52     {
     53         p=0;
     54         for(i=n-j;i<n;i++) y[p++]=i;
     55         for(i=0;i<n;i++)
     56          if(sa[i]>=j) y[p++]=sa[i]-j;
     57         for(i=0;i<n;i++) wd[i]=x[y[i]];
     58         for(i=0;i<m;i++) wc[i]=0;
     59         for(i=0;i<n;i++) wc[wd[i]]++; 
     60         for(i=1;i<m;i++) wc[i]+=wc[i-1];
     61         for(i=n-1;i>=0;i--) sa[--wc[wd[i]]]=y[i];
     62         swap(x,y);
     63         p=1; x[sa[0]]=0;
     64         for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     65     }
     66 }    
     67     
     68 void getheight(int *r,int *sa,int n)
     69 {
     70     int i,j,k=0;
     71     for(i=1;i<=n;i++) rank[sa[i]]=i;
     72     for(i=0;i<n;height[rank[i++]]=k)
     73     {
     74         if(k) k--;
     75         j=sa[rank[i]-1];
     76         while(r[i+k]==r[j+k]) k++;
     77     }
     78 }
     79 
     80 void init()
     81 {    
     82         memset(s,0,sizeof(s));
     83         memset(sa,0,sizeof(sa));
     84         memset(wa,0,sizeof(wa));
     85         memset(wb,0,sizeof(wb));
     86         memset(wc,0,sizeof(wc));
     87         memset(wd,0,sizeof(wd));
     88         memset(height,0,sizeof(height));
     89         memset(rank,0,sizeof(rank));
     90 }
     91 
     92 void solve(ll f,int L,int R)
     93 {
     94     //printf("%lld %d %d
    ",f,L,R);
     95     for(int i=L-1;i<=R+1;i++) H[i]=height[i];
     96     for(int i=L;i<=R;i++) c[i]=d[i]=0;
     97     stk[1]=L-1; H[L-1]=-oo; 
     98     int top=1;
     99     for(int i=L;i<=R;i++)
    100     {
    101         while(top&&H[i]<H[stk[top]]) top--;
    102         if(stk[top]==L-1) c[i]=L;
    103          else c[i]=stk[top]+1;
    104         stk[++top]=i;
    105     }
    106     stk[1]=R+1; H[R+1]=-oo;
    107     top=1;
    108     for(int i=R;i>=L;i--)
    109     {
    110         while(top&&H[i]<=H[stk[top]]) top--;
    111         if(stk[top]==R+1) d[i]=R;
    112          else d[i]=stk[top]-1;
    113         stk[++top]=i;
    114     } 
    115     ll tmp=0;
    116     for(int i=L;i<=R;i++) tmp=tmp+(-c[i]+i+1)*(d[i]-i+1)*height[i];
    117 //    printf("%lld
    ",tmp);
    118     ll t=R-L+1;
    119     tmp=tmp-K*(t+1)*t/2;
    120 //    printf("%lld
    ",tmp);
    121     for(int i=L;i<=R;i++) tmp=tmp+(-c[i]+i+1)*(d[i]-i+1);
    122 //    printf("%lld
    ",tmp);
    123     ans=ans+f*tmp;
    124 } 
    125     
    126 
    127 int main()
    128 {
    129     freopen("poj3415.in","r",stdin);
    130     freopen("poj3415.out","w",stdout); 
    131     while(scanf("%lld",&K)!=EOF)
    132     {
    133         if(K==0) break;
    134         ans=0;
    135         init();
    136         scanf("%s",a);
    137         int n1=strlen(a);
    138         scanf("%s",b);
    139         int n2=strlen(b);
    140         for(int i=0;i<n1;i++) 
    141          if('A'<=a[i]&&a[i]<='Z') s[i]=a[i]-'A'+2;
    142           else s[i]=a[i]-'a'+28;
    143         s[n1]=1;
    144         n=n1;
    145         getsa(s,sa,n+1,100);
    146         getheight(s,sa,n);
    147     
    148         int i=1;
    149         while(i<n)
    150         {
    151             i++;
    152             if(height[i]>=K)
    153             {
    154                 int st=i;
    155                 while(i<=n&&height[i]>=K) i++;
    156                 if(st<=i-1) solve(-1,st,i-1);
    157             }
    158         }
    159         //printf("%lld
    ",ans);
    160     
    161          
    162         init();
    163         for(int i=0;i<n2;i++) 
    164          if('A'<=b[i]&&b[i]<='Z') s[i]=b[i]-'A'+2;
    165           else s[i]=b[i]-'a'+28;
    166         s[n2]=1;
    167         n=n2;
    168         getsa(s,sa,n+1,100);
    169         getheight(s,sa,n);
    170         i=1;
    171         while(i<n)
    172         {
    173             i++;
    174             if(height[i]>=K)
    175             {
    176                 int st=i;
    177                 while(i<=n&&height[i]>=K) i++;
    178                 if(st<=i-1) solve(-1,st,i-1);
    179             }
    180         }
    181     //    printf("%lld
    ",ans);
    182     
    183         init();
    184         for(int i=0;i<n1;i++) 
    185          if('A'<=a[i]&&a[i]<='Z') s[i]=a[i]-'A'+2;
    186           else s[i]=a[i]-'a'+28;
    187         s[n1]=1;
    188         for(int i=0;i<n2;i++)
    189          if('A'<=b[i]&&b[i]<='Z') s[n1+i+1]=b[i]-'A'+2;
    190           else s[n1+i+1]=b[i]-'a'+28;
    191         s[n1+n2+1]=0;
    192         n=n1+n2+1;
    193         getsa(s,sa,n+1,100);
    194         getheight(s,sa,n);
    195     //    for(int i=1;i<=n;i++) printf("%d
    ",sa[i]);
    196         i=1;
    197         while(i<n)
    198         {
    199             i++;
    200             if(height[i]>=K)
    201             {
    202                 int st=i;
    203                 while(i<=n&&height[i]>=K) i++;
    204                 if(st<=i-1) solve(1,st,i-1);
    205             }
    206         }
    207         //for(int i=0;i<=n1+n2;i++) printf("%d
    ",sa[i]);
    208         //for(int i=2;i<=n1+n2+2;i++) printf("%d
    ",height[i]);
    209         printf("%lld
    ",ans);
    210     } 
    211     return 0;
    212 }
    213      
  • 相关阅读:
    matplotlib-形状
    matplotlib-区域填充
    C++文件操作
    画数学公式
    文字
    画注释
    Doubango简介-sip
    boost的asio接收单路大数据量udp包的方法
    Boost.Asio基本原理(CSDN也有Markdown了,好开森)
    boot asio 非阻塞同步编程---非阻塞的accept和receive。
  • 原文地址:https://www.cnblogs.com/myx12345/p/9642928.html
Copyright © 2020-2023  润新知