hdu 4552 怪盗基德的挑战书
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4552
思路:
其实可以用KMP+DP解决
我这里给出后缀数组的解题方法
思路:
初始化ans=n(n为字符串的长度)
然后你会发现答案就是ans加上每个后缀与最长后缀的最长公共前缀的长度
代码:
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 #define maxn 100010 7 int wa[maxn],wv[maxn],wb[maxn],wq[maxn]; 8 int height[maxn],rank[maxn],sa[maxn]; 9 int r[maxn]; 10 char s[maxn]; 11 int n; 12 int cmp(int *r,int a,int b,int l) 13 { 14 return r[a]==r[b]&& r[a+l]==r[b+l]; 15 } 16 void da(int n,int m) 17 { 18 int i,j,p,*x=wa,*y=wb,*t; 19 for(i=0;i<m;i++) wq[i]=0; 20 for(i=0;i<n;i++) wq[x[i]=r[i]]++; 21 for(i=1;i<m;i++) wq[i]+=wq[i-1]; 22 for(i=n-1;i>=0;i--) sa[--wq[x[i]]]=i; 23 24 for(j=1,p=1;p<n;j*=2,m=p) 25 { 26 for(p=0,i=n-j;i<n;i++) y[p++]=i; 27 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 28 for(i=0;i<n;i++) wv[i]=x[y[i]]; 29 for(i=0;i<m;i++) wq[i]=0; 30 for(i=0;i<n;i++) wq[wv[i]]++; 31 for(i=1;i<m;i++) wq[i]+=wq[i-1]; 32 for(i=n-1;i>=0;i--) sa[--wq[wv[i]]]=y[i]; 33 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) 34 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 35 36 } 37 return ; 38 } 39 void callheight(int n) 40 { 41 int i,j,k=0; 42 for(i=1;i<=n;i++) rank[sa[i]]=i; 43 for(i=0;i<n;i++) 44 { 45 if(k)k--; 46 j=sa[rank[i]-1]; 47 while(r[i+k]==r[j+k]) k++; 48 height[rank[i]]=k; 49 } 50 } 51 int main() 52 { 53 int Case=0; 54 while(scanf("%s",s)!=EOF) 55 { 56 n=strlen(s); 57 for(int i=0;i<n;i++) 58 r[i]=s[i]; 59 r[n]=0; 60 da(n+1,130); 61 callheight(n); 62 int ans=n; 63 int t=rank[0]; 64 int temp=n; 65 while(t<n)//加上排名在t后面的后缀与最长后缀的公共前缀长度 66 { 67 temp=min(temp,height[t+1]); 68 ans+=temp; 69 t++; 70 } 71 t=rank[0]; 72 temp=n; 73 while(t>1)//加上排名在t前面的后缀与最长后缀的公共前缀的长度 74 { 75 76 temp=min(temp,height[t]); 77 ans+=temp; 78 t--; 79 } 80 cout<<ans%256<<endl; 81 } 82 return 0; 83 }