zoukankan      html  css  js  c++  java
  • POJ3415 Common Substrings 后缀数组

      题目链接:http://poj.org/problem?id=3415

      求两个串的长度不小于K的公共字串的个数。

      利用height[]来维护一个单调递增的栈,即栈保存的是满足要求的heigiht数组的最小值,附加维护栈中相邻两个元素之间的个数。

      1 //STATUS:C++_AC_813MS_6532KB
      2 #include<stdio.h>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<math.h>
      6 #include<iostream>
      7 #include<string>
      8 #include<algorithm>
      9 #include<vector>
     10 #include<queue>
     11 #include<stack>
     12 #include<map>
     13 #include<set>
     14 using namespace std;
     15 //define
     16 #define pii pair<int,int>
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define lson l,mid,rt<<1
     19 #define rson mid+1,r,rt<<1|1
     20 #define PI acos(-1.0)
     21 //typedef
     22 typedef __int64 LL;
     23 typedef unsigned __int64 ULL;
     24 //const
     25 const int N=200010;
     26 const int INF=0x3f3f3f3f;
     27 const int MOD=1000007,STA=8000010;
     28 const LL LNF=1LL<<60;
     29 const double EPS=1e-8;
     30 const double OO=1e15;
     31 //Daily Use ...
     32 template<class T> inline T Min(T a,T b){return a<b?a:b;}
     33 template<class T> inline T Max(T a,T b){return a>b?a:b;}
     34 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
     35 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
     36 //
     37 
     38 struct Node{
     39     int l,cnt;
     40 }sta[N];
     41 
     42 char s[N/2];
     43 int num[N];
     44 int sa[N],t1[N],t2[N],c[N],rank[N],height[N];
     45 int n,m,len1,len2,K;
     46 LL ans;
     47 
     48 void build_sa(int s[],int n,int m)
     49 {
     50     int i,k,p,*x=t1,*y=t2;
     51     //第一轮基数排序
     52     for(i=0;i<m;i++)c[i]=0;
     53     for(i=0;i<n;i++)c[x[i]=s[i]]++;
     54     for(i=1;i<m;i++)c[i]+=c[i-1];
     55     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
     56     for(k=1;k<=n;k<<=1){
     57         p=0;
     58         //直接利用sa数组排序第二关键字
     59         for(i=n-k;i<n;i++)y[p++]=i;
     60         for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
     61         //基数排序第一关键字
     62         for(i=0;i<m;i++)c[i]=0;
     63         for(i=0;i<n;i++)c[x[y[i]]]++;
     64         for(i=1;i<m;i++)c[i]+=c[i-1];
     65         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
     66         //根据sa和x数组计算新的x数组
     67         swap(x,y);
     68         p=1;x[sa[0]]=0;
     69         for(i=1;i<n;i++)
     70             x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
     71         if(p>=n)break;   //已经排好序,直接退出
     72         m=p;     //下次基数排序的最大值
     73     }
     74 }
     75 
     76 void getHeight(int s[],int n)
     77 {
     78     int i,j,k=0;
     79     for(i=0;i<=n;i++)rank[sa[i]]=i;
     80     for(i=0;i<n;i++){
     81         if(k)k--;
     82         j=sa[rank[i]-1];
     83         while(s[i+k]==s[j+k])k++;
     84         height[rank[i]]=k;
     85     }
     86 }
     87 
     88 void slove(int flag)
     89 {
     90     int i,j,top=-1;
     91     LL sum=0;
     92     for(i=2;i<=n;i++){
     93         if(height[i]<K){top=-1;sum=0;continue;}
     94         j=0;
     95         if((sa[i-1]<len1)==flag)j=1,sum+=(LL)height[i]-K+1;
     96         for(;top>=0 && sta[top].l>=height[i];top--){
     97             sum-=(sta[top].l-height[i])*(LL)sta[top].cnt;
     98             j+=sta[top].cnt;
     99         }
    100         sta[++top].l=height[i];
    101         sta[top].cnt=j;
    102         if((sa[i]<len1)!=flag)
    103             ans+=sum;
    104     }
    105 }
    106 
    107 int main()
    108 {
    109  //   freopen("in.txt","r",stdin);
    110     int i,j;
    111     while(~scanf("%d",&K) && K)
    112     {
    113         scanf("%s",s);
    114         len1=strlen(s);
    115         for(i=0;i<len1;i++)num[i]=s[i]-'A'+1;
    116         scanf("%s",s);
    117         len2=strlen(s);
    118         num[i++]=80;
    119         for(j=0;j<len2;i++,j++)num[i]=s[j]-'A'+1;
    120         num[n=len1+len2+1]=0;
    121         m=81;
    122 
    123         build_sa(num,n+1,m);
    124         getHeight(num,n);
    125         ans=0;
    126         slove(1);
    127         slove(0);
    128 
    129         printf("%I64d\n",ans);
    130     }
    131     return 0;
    132 }
  • 相关阅读:
    CSS3旋转动画
    CSS3的动画属性
    CSS选择器
    JS事件委托
    js 轮播图效果
    JS事件冒泡和事件捕获
    JS自定义播放器
    js闭包for循环只执行最后一个值得解决方法
    交通红绿灯
    汉明距
  • 原文地址:https://www.cnblogs.com/zhsl/p/3043834.html
Copyright © 2011-2022 走看看