spoj 694 Distinct Substrings 705 New Distinct Substrings

    技术2022-05-18  14

    spoj 694 Distinct Substrings

    705 New Distinct Substrings

    题意:这两个题都是给你一个字符串让你求不相同的子串的个数。

    思路:因为没个子串都相当于这个字符串后缀的前缀,所以题目转换为求一个字符串所有后缀的不同前缀。

    比如:ababab

    sa height suff

    5 0 ab

    3       2 abab

    1 4 ababab

    6 0 b

    4 1 bab

    2 3 babab

    suff(sa[1]):ab,能产生的前缀:ab,a

    suff(sa[2]):abab,能产生的前缀:aba,abab其中:a,ab是重复的,重复的也就是height[i],

    suff(sa[i])能产生的不同的前缀有n-sa[i]+1那么多个,但是suff(sa[i+1])能产生的不同的字符串:n-sa[i]+1-height[i];

    只用从1到n全部加起来就是ans了。

    /* * File: main.cpp * Author: Mi * * Created on 2011年4月27日, 下午9:02 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <map> #include <vector> #include <stdlib.h> #define MAX 50005 using namespace std; /* * */ int wa[MAX],wb[MAX],ws[MAX],wv[MAX]; int r[MAX],sa[MAX]; char str[MAX]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];} void Da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(i=n-j,p=0;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return ; } int rank[MAX],height[MAX]; void Callheight(int *r,int *sa,int n) { int i,j,k=0; for(i=1;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); return ; } int main(int argc, char** argv) { int n,t,ans; scanf("%d",&t); while(t--) { ans=0; scanf("%s",str); for(n=0;str[n];n++) r[n]=str[n]; r[n]=0; Da(r,sa,n+1,256); Callheight(r,sa,n); for(int i=1;i<=n;i++) ans+=(n-sa[i]-height[i]); printf("%d/n",ans); } return 0; } 


    最新回复(0)