码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3230 相似子串

时间:2016-02-28 22:41:34      阅读:341      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

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

每个后缀贡献的子串数目是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\n";
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\n",ans);
139     }
140      return 0;
141 }

 

bzoj3230 相似子串

标签:

原文地址:http://www.cnblogs.com/HugeGun/p/5225739.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!