• bzoj3230 相似子串


    题目链接

    每个子串都是一个后缀的前缀

    每个后缀贡献的子串数目是len-sa[i]-height[i];

    因此可以二分找到一个子串的位置,要求某两个子串的最长公共前缀和最长公共后缀,把原串倒过再来一发就好,然后st表O(1)查询;

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<string>
      7 #include<cmath>
      8 #include<ctime>
      9 #include<queue>
     10 #include<stack>
     11 #include<map>
     12 #include<set>
     13 #define rre(i,r,l) for(int i=(r);i>=(l);i--)
     14 #define re(i,l,r) for(int i=(l);i<=(r);i++)
     15 #define Clear(a,b) memset(a,b,sizeof(a))
     16 #define inout(x) printf("%d",(x))
     17 #define douin(x) scanf("%lf",&x)
     18 #define strin(x) scanf("%s",(x))
     19 #define LLin(x) scanf("%lld",&x)
     20 #define op operator
     21 #define CSC main
     22 typedef unsigned long long ULL;
     23 typedef const int cint;
     24 typedef long long LL;
     25 using namespace std;
     26 void inin(int &ret)
     27 {
     28     ret=0;int f=0;char ch=getchar();
     29     while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
     30     while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar();
     31     ret=f?-ret:ret;
     32 }
     33 char s[100010];
     34 int LOG[100010],n,q;
     35 cint inf=2147483647;
     36 struct string
     37 {
     38     int sa[100010],h[100010],t[100010],t2[100010],c[100010],rank[100010];
     39     LL sum[100010];
     40     int f[100010][20];
     41     void build_sa(int m)
     42     {
     43         int *x=t,*y=t2;
     44         re(i,0,m-1)c[i]=0;
     45         re(i,0,n-1)x[i]=s[i],c[x[i]]++;
     46         re(i,1,m-1)c[i]+=c[i-1];
     47         rre(i,n-1,0)sa[--c[x[i]]]=i;
     48         for(int k=1;k<=n;k<<=1)
     49         {
     50             int p=0;
     51             rre(i,n-1,n-k)y[p++]=i;
     52             re(i,0,n-1)if(sa[i]>=k)y[p++]=sa[i]-k;
     53             re(i,0,m-1)c[i]=0;
     54             re(i,0,n-1)c[x[y[i]]]++;
     55             re(i,1,m-1)c[i]+=c[i-1];
     56             rre(i,n-1,0)sa[--c[x[y[i]]]]=y[i];
     57             swap(x,y);
     58             x[sa[0]]=0;p=1;
     59             re(i,1,n-1)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
     60             if(p>=n)return ;
     61             m=p;
     62         }
     63     }
     64     void build_height()//
     65     {
     66         int k=0;
     67         re(i,0,n-1)rank[sa[i]]=i;
     68         re(i,0,n-1)
     69         {
     70             if(k)k--;
     71             if(!rank[i])continue ;
     72             int j=sa[rank[i]-1];
     73             while(s[i+k]==s[j+k])k++;
     74             h[rank[i]]=k;
     75         }
     76     }
     77     void build_sum()//
     78     {
     79         sum[0]=n-sa[0];
     80         re(i,1,n-1)sum[i]=sum[i-1]+n-h[i]-sa[i];
     81     }
     82     void build_RMQ()//
     83     {
     84         re(i,1,n-1)f[i][0]=h[i];
     85         for(int j=1;(1<<j)<n;j++)
     86             for(int i=1;i+(1<<(j-1))<n;i++)
     87                 f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
     88     }
     89     void init()
     90     {
     91         build_sa(256);
     92         build_height();
     93         build_sum();
     94         build_RMQ();
     95     }
     96     void find(LL wei,int &a,int &b)//
     97     {
     98         int x=lower_bound(sum,sum+n,wei)-sum;
     99         a=sa[x],b=sa[x]+h[x]+wei-(x?sum[x-1]:0);
    100     }
    101     int query(int l,int r)//
    102     {
    103         l=rank[l],r=rank[r];
    104         if(r<l)swap(l,r);l++;
    105         int k=LOG[r-l+1];
    106         return min(f[l][k],f[r-(1<<k)+1][k]);
    107     }
    108 }A,B;
    109 int main()
    110 {
    111     freopen("in.in","r",stdin);
    112     freopen("out.out","w",stdout);
    113     inin(n),inin(q);
    114     LOG[0]=-1;
    115     re(i,1,100000)LOG[i]=LOG[i>>1]+1;
    116     strin(s);
    117     A.init();
    118     reverse(s,s+n);
    119     B.init();
    120     while(q--)
    121     {
    122         int a1,b1,a2,b2,t;
    123         LL l,r,ans=0;
    124         LLin(l),LLin(r);
    125         if(l>A.sum[n-1]||r>A.sum[n-1])
    126         {
    127             cout<<"-1
    ";
    128             continue;
    129         }
    130         A.find(l,a1,b1);
    131         A.find(r,a2,b2);
    132         t=a1==a2?inf:A.query(a1,a2);
    133         t=min(t,min(b1-a1,b2-a2));
    134         ans+=(LL)t*t;
    135         t=b1==b2?inf:B.query(n-b1,n-b2);
    136         t=min(t,min(b1-a1,b2-a2));
    137         ans+=(LL)t*t;
    138         printf("%lld
    ",ans);
    139     }
    140      return 0;
    141 }
  • 相关阅读:
    一个很诡异的javascript问题
    记录我开发鞋服行业供应链软件的历程<设计业务层>
    为什么要自已写报表中心
    关于系统的性能
    “时间”都去哪儿了?性能调优分析方法与案例详解
    工程师推荐软件
    终于有人把云计算、大数据和人工智能讲明白了!
    C# Dictionary 泛型字典集合(转)
    DEV中的TreeList控件应用的一个小效果实现
    推荐VS2008插件CodeRush Xpress for C#
  • 原文地址:https://www.cnblogs.com/HugeGun/p/5225739.html
Copyright © 2020-2023  润新知