题目大意:
串1中有多少个后缀和 串2中的某个后缀 的lcp 为 k
思路分析:
先找出 长度至少为k的对数有多少。
再找出 至少为k+1的有多少
然后相减。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <map> #include <string> #define maxn 110005 using namespace std; int str[maxn]; int sa[maxn],t1[maxn],t2[maxn],c[maxn],n; void suffix(int m) { int *x=t1,*y=t2; for(int i=0; i<m; i++)c[i]=0; for(int i=0; i<n; i++)c[x[i]=str[i]]++; for(int i=1; i<m; i++)c[i]+=c[i-1]; for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i; for(int k=1; k<=n; k<<=1) { int p=0; for(int i=n-k; i<n; i++)y[p++]=i; for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(int i=0; i<m; i++)c[i]=0; for(int i=0; i<n; i++)c[x[y[i]]]++; for(int i=0; i<m; i++)c[i]+=c[i-1]; for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(int i=1; i<n; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; m=p; } } int rank[maxn],height[maxn]; void getheight() { int k=0; for(int i=0; i<n; i++)rank[sa[i]]=i; for(int i=0; i<n; i++) { if(k)k--; if(!rank[i])continue; int j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; } } int tmp[50005]; int solve(int k,int nn) { int ans=0; int res=0,ret=0; for(int i=1; i<n; i++) { if(height[i]<k) { if(ret) ans+=res; res=ret=0; if(sa[i]<nn)res++; else ret++; } else { if(sa[i]<nn)res++; else ret++; } } if(ret)ans+=res; return ans; } int main() { int nn,mm,k; while(scanf("%d%d%d",&nn,&mm,&k)!=EOF) { int top=0; for(int i=1; i<=nn; i++) { scanf("%d",&tmp[i]); tmp[i]+=2; str[top++]=tmp[i]; } str[top++]=1; for(int i=1; i<=mm; i++) { scanf("%d",&tmp[i]); tmp[i]+=2; str[top++]=tmp[i]; } str[top++]=0; n=top; suffix(10005); getheight(); printf("%d\n",solve(k,nn)-solve(k+1,nn)); } return 0; }
POJ 3729 Facer’s string (后缀数组)
时间: 2024-10-15 16:49:32