HUST 1328求每一个前缀在串中出现次数和

Description

Give you a string S,assume the Sub-String Stri = S[0..i] and the length of the string is N. e.g. S = "moreandmorecold", N = 15, Str0 = "m" Str1 = "mo" Str2 = "mor" and so on.
And we define c[i] indicate how many Sub-String Stri in S, now please calculate the sum of c[0] to c[N-1].

Input

The first line include a number T, means the number of test cases.
For each test case, just a line only include lowercase indicate the String S, the length of S will less than 100000.

Output

Fore each test case, just a number means the sum.

Sample Input

3
acacm
moreandmorecold
thisisthisththisisthisisthisththisis

Sample Output

7
19
82

For the first case,
there are two "a","ac" and one "aca","acac","acacm" in the string "acacm".
So the answer is 2 + 2 + 1 + 1 + 1 = 7


题意:给定一个串,求前缀在串中出现次数之和。

解题思路:假设字符串的长度为n,首先肯定会有n个串出现,剩下的部分就是中间一些串可能与前面的相同,这个根据

每一个后缀与后缀0的最长公共前缀叠加得出。

代码:

/* ***********************************************
Author :xianxingwuguan
Created Time :2014-1-29 20:43:51
File Name :4.cpp
************************************************ */

#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn=300300;
int height[maxn],sa[maxn],rank[maxn],c[maxn],t1[maxn],t2[maxn];  
void da(int *str,int n,int m)  
{  
      int i,j,k,p,*x=t1,*y=t2;  
      for(i=0;i<m;i++)c[i]=0;  
      for(i=0;i<n;i++)c[x[i]=str[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(k=1;k<=n;k<<=1)  
      {  
         p=0;  
         for(i=n-k;i<n;i++)y[p++]=i;  
         for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;  
         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]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;  
         if(p>=n)break;  
         m=p;  
      }  
}  
void calheight(int *str,int n)  
{  
      int i,j,k=0;  
      for(i=0;i<=n;i++)rank[sa[i]]=i;  
      for(i=0;i<n;i++)  
      {  
         if(k)k--;  
         j=sa[rank[i]-1];  
         while(str[i+k]==str[j+k])k++;  
         height[rank[i]]=k;  
      }  
         // printf("sa:");for(i=0;i<=n;i++)printf("%d ",sa[i]);puts("");  
         // printf("rank:");for(i=0;i<=n;i++)printf("%d ",rank[i]);puts("");  
         // printf("height:");for(i=0;i<=n;i++)printf("%d ",height[i]);puts("");  
      
}  
int str[maxn];  
char ss[maxn];  
int Log[maxn];  
int best[23][maxn];  
void init(int n)  
{  
      int i,j;  
      Log[0]=-1;  
      for(i=1;i<=n;i++)  
         Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1;  
      for(i=1;i<=n;i++)best[0][i]=height[i];  
      for(i=1;i<=Log[n];i++)  
         for(j=1;j<=n;j++)  
            best[i][j]=min(best[i-1][j],best[i-1][j+(1<<(i-1))]);  
}  
int lcp(int a,int b)  
{  
      a=rank[a];  
      b=rank[b];  
      if(a>b)swap(a,b);  
      a++;  
      int t=Log[b-a+1];  
      return min(best[t][a],best[t][b-(1<<t)+1]);  
}  
int rep[maxn];
int main()
{
      //freopen("data.in","r",stdin);
      //freopen("data.out","w",stdout);
      int i,j,k,m,n,p,T;
      scanf("%d",&T);
      while(T--)
      {
	     scanf("%s",ss);
	     n=strlen(ss);
	     for(i=0;i<n;i++)str[i]=ss[i];
	     str[n]=0;
	     da(str,n+1,300);
	     calheight(str,n);
	     init(n);
            long long ans=n;
	     for(i=1;i<n;i++)
		    ans+=lcp(0,i);
	     printf("%lld\n",ans);
      }
      return 0;
}



HUST 1328求每一个前缀在串中出现次数和

上一篇:UVA - 1443 Garlands (二分+DP)


下一篇:HUST 1352 求重复次数不小于k的子串的个数。