【HDU4552】 怪盗基德的挑战书(后缀数组)
怪盗基德的挑战书
Problem Description“在树最美丽的那天,当时间老人再次把大钟平均分开时,我会降临在灯火之城的金字塔前,带走那最珍贵的笑容。”这是怪盗基德盗取巴黎卢浮宫的《蒙娜丽莎的微笑》这幅画时,挑战书上的内容。
但这次,怪盗基德的挑战书上出现了一串串小写字母“aaab sdfeeddd...”。柯南以小学生的眼睛,超凡高中生的头脑,快速统计各种字母频率,字符串长度,并结合挑战书出现的时间等信息,试图分析怪盗基德的意图。最后,他将线索锁定在字符串的循环次数上。并且进一步推理发现,从字符串的第一位开始,到第i位,形成该字符串的子串(c1, c2, c3 ... ci )。对于某一子串ci在该字符串中出现的次数记为ki,则全部子串的循环次数总和AIM = k1 + k2 + ... + ki + ... + kn,柯南发现,AIM恰好对应一个ASCII码!所以,只要把挑战书上的字符串转变成数字,再找到对应的ASCII码,就可以破解这份挑战书了!
现在,你的任务就是把字符串转变成对应数字,因为ASCII码以及扩展ASCII码全部只有256个,所以,本题只要把结果对256取余即可。Input输入有多组测试数据;
每组测试数据只有一个字符串,由各种小写字母组成,中间无空格。
字符串的长度为L(0 < L <= 100000)。Output请计算并输出字符串的AIM值,每组数据输出一行。Sample InputaaaababSample Output6 6
【题意】
给一个串s,求s的每个前缀出现次数之和。
【分析】
用后缀数组求的话,就是求出每个后缀和最长的后缀的公共前缀长度就可以了。
就是rank[1]的位置往两边找。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define INF 0xfffffff 9 #define Maxl 100010 10 #define Mod 256 11 12 int k,la; 13 char a[Maxl],b[Maxl]; 14 int c[Maxl]; 15 int cl; 16 17 int sa[Maxl],rk[Maxl],Rs[Maxl],wr[Maxl],y[Maxl]; 18 //sa -> 排名第几的是谁 19 //rk -> i的排名 20 //Rs数值小于等于i的有多少个 21 //y -> 第二关键字排名第几的是谁(类似sa) 22 int height[Maxl]; 23 24 int mymin(int x,int y) {return x<y?x:y;} 25 26 void get_sa(int m) 27 { 28 memcpy(rk,c,sizeof(rk)); 29 for(int i=0;i<=m;i++) Rs[i]=0; 30 for(int i=1;i<=cl;i++) Rs[rk[i]]++; 31 for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1]; 32 for(int i=cl;i>=1;i--) sa[Rs[rk[i]]--]=i; 33 34 int ln=1,p=0; 35 while(p<cl) 36 { 37 int k=0; 38 for(int i=cl-ln+1;i<=cl;i++) y[++k]=i; 39 for(int i=1;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln; 40 for(int i=1;i<=cl;i++) wr[i]=rk[y[i]]; 41 42 for(int i=0;i<=m;i++) Rs[i]=0; 43 for(int i=1;i<=cl;i++) Rs[wr[i]]++; 44 for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1]; 45 for(int i=cl;i>=1;i--) sa[Rs[wr[i]]--]=y[i]; 46 47 for(int i=1;i<=cl;i++) wr[i]=rk[i]; 48 for(int i=cl+1;i<=cl+ln;i++) wr[i]=0; 49 p=1;rk[sa[1]]=1; 50 for(int i=2;i<=cl;i++) 51 { 52 if(wr[sa[i]]!=wr[sa[i-1]]||wr[sa[i]+ln]!=wr[sa[i-1]+ln]) p++; 53 rk[sa[i]]=p; 54 } 55 m=p,ln*=2; 56 } 57 sa[0]=rk[0]=0; 58 } 59 60 void get_he() 61 { 62 int kk=0; 63 for(int i=1;i<=cl;i++) 64 { 65 int j=sa[rk[i]-1]; 66 if(kk) kk--; 67 while(c[i+kk]==c[j+kk]&&i+kk<=cl&&j+kk<=cl) kk++; 68 height[rk[i]]=kk; 69 } 70 } 71 72 void ffind() 73 { 74 int ans=0,minn=INF; 75 ans+=cl; 76 for(int i=rk[1];i>=2;i--) 77 { 78 minn=mymin(minn,height[i]); 79 ans=(ans+minn)%Mod; 80 }minn=INF; 81 for(int i=rk[1]+1;i<=cl;i++) 82 { 83 minn=mymin(minn,height[i]); 84 ans=(ans+minn)%Mod; 85 } 86 printf("%d\n",ans); 87 } 88 89 int main() 90 { 91 while(scanf("%s",a)!=EOF) 92 { 93 cl=strlen(a); 94 for(int i=0;i<cl;i++) c[i+1]=a[i]-'a'+1; 95 get_sa(30); 96 get_he(); 97 ffind(); 98 } 99 return 0; 100 }
2016-07-17 15:50:30