HDU - 3518 Boring counting (suffix array)

Topic links: Click here

Title effect: Given a string, asked how many substring occurs twice or more, the calculation can not overlap each other

Topic Analysis: Since the data range is relatively small, we can direct violence, enumerate substring length, using the height of the nature of the suffix array is divided into different groups, try to find the answer in each group to

Code:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;
 
const int N=1e3+100;
 
char str[N];
 
int sa[N]; //SA数组,表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[N],t2[N],c[N];
 
int rk[N],height[N],len;
 
int s[N];
 
void build_sa(int s[],int n,int m)//n为添加0后的总长
{
    int i,j,p,*x=t1,*y=t2;
    for(i=0;i<m;i++) 
		c[i]=0;
    for(i=0;i<n;i++) 
		c[x[i]=s[i]]++;
    for(i=1;i<m;i++) 
		c[i]+=c[i-1];
    for(i=n-1;i>=0;i--) 
		sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1) 
	{
        p=0;
        for(i=n-j;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<m;i++) 
			c[i]=0;
        for(i=0;i<n;i++) 
			c[x[y[i]]]++;
        for(i=1;i<m;i++) 
			c[i]+=c[i-1];
        for(i=n-1;i>=0;i--) 
			sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1,x[sa[0]]=0;
        for(i=1;i<n;i++) 
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n) 
			break;
        m=p;
    }
}
 
void get_height(int s[],int n)//n为添加0后的总长
{
    int i,j,k=0;
    for(i=0;i<=n;i++)
        rk[sa[i]]=i;
    for(i=0;i<n;i++) 
	{
        if(k) 
			k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k]) 
			k++;
        height[rk[i]]=k;
    }
}
 
void solve(int base=128)
{
	build_sa(s,len+1,base);
	get_height(s,len);
}

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	while(scanf("%s",str)!=EOF&&str[0]!='#')
	{
		len=strlen(str);
		for(int i=0;i<len;i++)
			s[i]=str[i]-'a'+1;
		s[len]=0;
		solve(30);
		int ans=0;
		for(int i=1;i<=len/2;i++)
		{
			int mmax=-inf,mmin=inf;
			for(int j=2;j<=len;j++)
			{
				if(height[j]>=i)
				{
					mmax=max(mmax,max(sa[j],sa[j-1]));
					mmin=min(mmin,min(sa[j],sa[j-1]));
				}
				else
				{
					if(mmax-mmin>=i)
						ans++;
					mmax=-inf;
					mmin=inf;
				}
			}
			if(mmax-mmin>=i)
				ans++;
		}
		printf("%d\n",ans);
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	return 0;
}

 

Published 558 original articles · won praise 16 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_45458915/article/details/104081115