记录编号 294074 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2016]优秀的拆分 最终得分 100
用户昵称 GravatarTenderRun 是否通过 通过
代码语言 C++ 运行时间 6.521 s
提交时间 2016-08-11 16:50:46 内存使用 74.75 MiB
显示代码纯文本
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=120010;
struct SAM{
	char s[N];
	int fa[N],pos[N],sa[N],rank[N];
	int son[N][26],end[N],rht[N],lcp[N];
	int ch[N][26],len[N],id[N],tot;
	int od[N],wv[N],lst,cnt;
	int mm[N],Min[N][25];
	void Init(){
		memset(s,0,sizeof(s)); 
		memset(ch,0,sizeof(ch));
		memset(end,0,sizeof(end));
		memset(son,0,sizeof(son));
		memset(pos,0,sizeof(pos));
		lst=cnt=1;tot=0;
	}

	void Insert(int c){
		int p=lst,np=lst=++cnt;end[lst]=1;
		id[len[np]=len[p]+1]=np;rht[np]=1;
		while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
		if(!p)fa[np]=1;
		else{
			int q=ch[p][c],nq;
			if(len[q]==len[p]+1)fa[np]=q;
			else{
				len[nq=++cnt]=len[p]+1;
				fa[nq]=fa[q];fa[q]=fa[np]=nq;
				memcpy(ch[nq],ch[q],sizeof(ch[q]));
				while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
			}
		}
	}

	void Get_Right(){
		for(int i=1;i<=cnt;i++)wv[len[i]]++;
		for(int i=1;i<=cnt;i++)wv[i]+=wv[i-1];
		for(int i=1;i<=cnt;i++)od[wv[len[i]]--]=i;
		for(int i=cnt;i>=1;i--)rht[fa[od[i]]]+=rht[od[i]];
	}

	void Build_Tree(){
		int l=strlen(s+1);
		for(int i=l;i>=1;i--)Insert(s[i]-'a');
		for(int i=l;i>=1;i--)
			for(int x=id[i],p=l+1;x&&!pos[x];x=fa[x])
				p-=len[x]-len[fa[x]],pos[x]=p;
		for(int x=2;x<=cnt;x++)son[fa[x]][s[pos[x]]-'a']=x;	
	}

	void DFS(int x,int l){
		if(end[x])sa[rank[l-len[x]+1]=++tot]=l-len[x]+1;
		for(int i=0;i<26;i++)if(son[x][i])DFS(son[x][i],l);
	}

	void Build_SA(){
		int l=strlen(s+1),k=0;DFS(1,l);
		for(int i=1,j;i<=l;lcp[rank[i++]]=k)
			for(k?k--:k,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);
		mm[0]=-1;
		for(int i=1;i<=l;i++){
			mm[i]=(i&(i-1))?mm[i-1]:mm[i-1]+1;
			Min[i][0]=lcp[i];
		}
		for(int k=1;k<=mm[l];k++)
			for(int i=1;i+(1<<k-1)<=l;i++)
				Min[i][k]=min(Min[i][k-1],Min[i+(1<<(k-1))][k-1]);
	}
	
	int LCP(int x,int y){
		if(x>y)swap(x,y);x+=1;int k=mm[y-x+1];
		int ret=min(Min[x][k],Min[y-(1<<k)+1][k]);
		return ret; 
	}
}A,B;

int ln,T,f[N],g[N];char s[N];
int Get_LCP(int x,int y){return A.LCP(A.rank[x],A.rank[y]);}
int Get_LCS(int x,int y){return B.LCP(B.rank[ln-x+1],B.rank[ln-y+1]);} 

int main(){
	freopen("excellent.in","r",stdin);
	freopen("excellent.out","w",stdout);
	scanf("%d",&T);
	while(T--){
		A.Init();B.Init();
		scanf("%s",s+1);ln=strlen(s+1);
		for(int i=1;i<=ln;i++){A.s[i]=s[i];B.s[i]=s[ln-i+1];}
		A.Build_Tree();A.Build_SA();
		B.Build_Tree();B.Build_SA();
		for(int i=1;i<=ln;i++)f[i]=g[i]=0;
	    
	    for(int i=1,l,r,x;i+i<=ln;i++)
			for(int j=i;(x=j+i)<=ln;j+=i)if(s[j]==s[x]){
				l=x-Get_LCS(j,x)+1;r=x+Get_LCP(j,x)-1;
				l=max(l+i-1,x);r=min(r,x+i-1);
				if(l>r)continue;
				f[l]++,f[r+1]--;
       			g[l-i-i+1]++,g[r+1-i-i+1]--;
	    	}
		long long ans=0;
		for(int i=1;i<=ln;i++)f[i]+=f[i-1],g[i]+=g[i-1];
		for(int i=1;i<ln;i++)ans+=f[i]*g[i+1];
		printf("%lld\n",ans);
	}
	return 0;
}