zoukankan      html  css  js  c++  java
  • 【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      
  • 相关阅读:
    03_ if 练习 _ little2big
    uva 11275 3D Triangles
    uva 12296 Pieces and Discs
    uvalive 3218 Find the Border
    uvalive 2797 Monster Trap
    uvalive 4992 Jungle Outpost
    uva 2218 Triathlon
    uvalive 3890 Most Distant Point from the Sea
    uvalive 4728 Squares
    uva 10256 The Great Divide
  • 原文地址:https://www.cnblogs.com/myx12345/p/9642928.html
Copyright © 2011-2022 走看看