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      
  • 相关阅读:
    atitit.nfc 身份证 银行卡 芯片卡 解决方案 attilax总结
    atitit.php 流行框架 前三甲为:Laravel、Phalcon、Symfony2 attilax 总结
    Atitit.执行cmd 命令行 php
    Atitit. 图像处理jpg图片的压缩 清理垃圾图片 java版本
    atitit。企业组织与软件工程的策略 战略 趋势 原则 attilax 大总结
    atitit. 管理哲学 大毁灭 如何防止企业的自我毁灭
    Atitit.java的浏览器插件技术 Applet japplet attilax总结
    Atitit.jquery 版本新特性attilax总结
    Atitit. 软件开发中的管理哲学一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向
    (转)获取手机的IMEI号
  • 原文地址:https://www.cnblogs.com/myx12345/p/9642928.html
Copyright © 2011-2022 走看看