題目
題解
後綴數組暴力水過。。。
時間複雜度O(n^3)
AC代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn=1100;
int ranka[maxn+1],tmp[maxn+1],n,k;
bool compare_sa(int i,int j)
{
if(ranka[i]!=ranka[j]) return ranka[i]<ranka[j];
else
{
int ri=i+k<=n?ranka[i+k]:-1;
int rj=j+k<=n?ranka[j+k]:-1;
return ri<rj;
}
}
void construct_sa(string s,int *sa)
{
n=s.size();
for(int i=0;i<=n;i++)
{
sa[i]=i;
ranka[i]=i<n?s[i]:-1;
}
for(k=1;k<=n;k*=2)
{
sort(sa,sa+n+1,compare_sa);
//tmp不能省
tmp[sa[0]]=0;
for(int i=1;i<=n;i++)
{
tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0);//括號必須加
}
for(int i=0;i<=n;i++) ranka[i]=tmp[i];
}
}
void construct_lcp(string s,int *sa,int *lcp)
{
int n=s.length();
for(int i=0;i<=n;i++) ranka[sa[i]]=i;//取消相同排名
int h=0;
lcp[0]=0;//空串與第一個後綴的最長公共前綴爲空
for(int i=0;i<n;i++)
{
//計算字符串中從位置i開始的後綴和其在後綴數組中的前一個後綴的LCP
int j=sa[ranka[i]-1];
//將h先減去首字母的1長度,在保持前綴相同前提下不斷增加
if(h>0) h--;
for(;j+h<n && i+h<n;h++)
{
if(s[j+h]!=s[i+h]) break;
}
lcp[ranka[i]-1]=h;
}
}
int ans[1100];
int main()
{
// ios::sync_with_stdio(false);
string s;
int sa[maxn],lcp[maxn];
while(cin>>s)
{
int len=s.size();
//求後綴數組
construct_sa(s,sa);
//求高度數組
construct_lcp(s,sa,lcp);
//輸出
int T;
//cin>>T;
scanf("%d",&T);
memset(ans,0,sizeof(ans));
while(T--)
{
int pos,sum=0;
//cin>>pos;
scanf("%d",&pos);
pos--;
if(ans[pos]){
//cout<<ans[pos]<<endl;
printf("%d\n",ans[pos]);
continue;
}
for(int i=1;i<len;i++)
{
int now=lcp[i];
for(int j=i+1;j<=len;j++)
{
now=min(now,lcp[j-1]);
if((sa[i]<=pos)!=sa[j]<=pos)
{
int x=sa[i]<=pos?i:j;
sum+=min(pos-sa[x]+1,now);
}
if(now==0) break;
}
}
ans[pos]=sum;
//cout<<sum<<endl;
printf("%d\n",sum);
}
// for(int i=0;i<=len;i++)
// {
// cout<<i<<" "<<sa[i]<<" "<<lcp[i]<<endl;
// }
}
return 0;
}