2 bbaba 5 3 4 2 2 2 5 2 4 1 4 baaba 5 3 3 3 4 1 4 3 5 5 5
3 1 7 5 8 1 3 8 5 1HintI won‘t do anything against hash because I am nice.Of course this problem has a solution that don‘t rely on hash.
#include<algorithm> #include<iostream> #include<string.h> #include<stdio.h> using namespace std; const int INF=0x3f3f3f3f; const int maxn=2010; typedef long long ll; char txt[maxn]; int sa[maxn],T1[maxn],T2[maxn],ct[maxn],he[maxn],rk[maxn],n,m; void getsa(char *st) { int i,k,p,*x=T1,*y=T2; for(i=0; i<m; i++) ct[i]=0; for(i=0; i<n; i++) ct[x[i]=st[i]]++; for(i=1; i<m; i++) ct[i]+=ct[i-1]; for(i=n-1; i>=0; i--) sa[--ct[x[i]]]=i; for(k=1,p=1; p<n; k<<=1,m=p) { for(p=0,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++) ct[i]=0; for(i=0; i<n; i++) ct[x[y[i]]]++; for(i=1; i<m; i++) ct[i]+=ct[i-1]; for(i=n-1; i>=0; i--) sa[--ct[x[y[i]]]]=y[i]; for(swap(x,y),p=1,x[sa[0]]=0,i=1; i<n; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; } } void gethe(char *st) { int i,j,k=0; for(i=0;i<n;i++) rk[sa[i]]=i; for(i=0;i<n-1;i++) { if(k) k--; j=sa[rk[i]-1]; while(st[i+k]==st[j+k]) k++; he[rk[i]]=k; } } int main() { int t,i,q,le,ri,lcp,ml,ans,tp; scanf("%d",&t); while(t--) { scanf("%s",txt); n=strlen(txt)+1; m=150; getsa(txt); gethe(txt); scanf("%d",&q); while(q--) { scanf("%d%d",&le,&ri); le--,ri--; ans=lcp=ml=0; for(i=1;i<n;i++) { lcp=min(lcp,he[i]); ml=min(ml,lcp); if(sa[i]>=le&&sa[i]<=ri) { ans+=ri-sa[i]+1-min(ri-sa[i]+1,ml); lcp=he[i+1]; tp=min(lcp,ri-sa[i]+1); ml=max(ml,tp); } } printf("%d\n",ans); } } return 0; } /* 1 lelwprbultllgkhhhyjchhngo 1 15 21 */第二种方法是后缀自动机。这个方法就比较简单了(不代表后缀自动机简单)。后缀自动机花了很长时间才懂。主要原因感觉网上这方面通俗的资料比较少。也可能是自己太弱了吧。后缀自动机是我学的感觉学起来最难的算法没有之一。打算打完现场赛自己写个简单的学习笔记来拯救像我这样苦逼的少年。这题只需在后缀自动机结点里多维护个信息记录到该节点有多少不同子串就行了。每次就可以知道增加了多少子串。建n次后缀自动机预处理出所有答案就好啦。
#include<algorithm> #include<iostream> #include<string.h> #include<stdio.h> using namespace std; const int INF=0x3f3f3f3f; const int maxn=2010<<1; typedef long long ll; struct node { node *f,*ch[30]; int len,way; void init() { way=0; memset(ch,0,sizeof ch); } }*root,*tail,sam[maxn<<1]; int tot,dp[2010][2010]; char txt[maxn]; void init() { tot=0; root=tail=&sam[tot++]; root->f=NULL; root->len=0; root->init(); root->way=1; } void Insert(int c) { node *p=tail,*np=&sam[tot++]; np->init(),np->len=p->len+1; while(p&&!p->ch[c]) { np->way+=p->way; p->ch[c]=np,p=p->f; } tail=np; if(!p) np->f=root; else { if(p->ch[c]->len==p->len+1) np->f=p->ch[c]; else { node *q=p->ch[c],*nq=&sam[tot++]; *nq=*q; nq->len=p->len+1; nq->way=0; q->f=np->f=nq; while(p&&p->ch[c]==q) { p->ch[c]->way-=p->way; nq->way+=p->way; p->ch[c]=nq,p=p->f; } } } } int main() { int i,j,t,len,q,le,ri; scanf("%d",&t); while(t--) { scanf("%s",txt); len=strlen(txt); for(i=0;i<len;i++) { init(); for(j=i;j<len;j++) { Insert(txt[j]-'a'); dp[i][j]=tail->way; } for(j=i+1;j<len;j++) dp[i][j]+=dp[i][j-1]; } scanf("%d",&q); while(q--) { scanf("%d%d",&le,&ri); printf("%d\n",dp[le-1][ri-1]); } } return 0; }
hdu 4622 Reincarnation(后缀数组|后缀自动机|KMP)
原文地址:http://blog.csdn.net/bossup/article/details/40191095