[POJ2406]字符串的幂

题目描述】

对于给定的两个字符串a,b,我们定义a*b是将把它们连接在一起形成的字符串。例如,若a="abc",b="def",则a*b="abcdef"。如果我们将这种运算视为乘法,则非负整数的乘方运算被以类似的方式定义:a^0=""(空字符串),a^(n+1)=a*(a^n)。

【输入格式】

输入包含多组数据。

每组数据有一行一个大写字母组成的字符串s,其长度至少为1,至多为10^6.输入结束标志为一行一个“.”(半角句号)。

【输出格式】

输出使得存在某个a,使得a^n=s的最大n。

【样例输入】

ABCD
AAAA
ABABAB
.

【样例输出】

1
4
3

 题解:

容易题,可后缀数组被卡了常,于是上了KMP 显然答案即为 n/(n-next[n]+1)

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 const int N=1e6+5;
 9 char S[N];int n,s[N],c[50],rk[N],x[N],y[N],sa[N],k,f[N][22],high[N];
10 void Getsa(){
11     int m=29,t;
12     for(int i=0;i<=m;i++)c[i]=0;
13     for(int i=1;i<=n;i++)c[x[i]=s[i]]++;
14     for(int i=1;i<=m;i++)c[i]+=c[i-1];
15     for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
16     for(k=1;k<=n;k<<=1){
17         t=0;
18         for(int i=0;i<=m;i++)y[i]=0;
19         for(int i=n-k+1;i<=n;i++)y[++t]=i;
20         for(int i=1;i<=n;i++)if(sa[i]>k)y[++t]=sa[i]-k;
21         for(int i=0;i<=m;i++)c[i]=0;
22         for(int i=1;i<=n;i++)c[x[i]]++;
23         for(int i=1;i<=m;i++)c[i]+=c[i-1];
24         for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i];
25         swap(x,y);
26         x[sa[1]]=t=1;
27         for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k])?t:++t;
28         if(t==n)break;
29         m=t;
30     }
31     for(int i=1;i<=n;i++)rk[sa[i]]=i;
32 }
33 void Gethight(){
34     int h=0,j;
35     for(int i=1;i<=n;i++){
36         j=sa[rk[i]-1];
37         if(h)h--;
38         for(;i+h<=n && j+h<=n;h++)if(s[i+h]!=s[j+h])break;
39         high[rk[i]-1]=h;
40     }
41 }
42 void prework(){
43     int tmp,to;
44     for(int i=1;i<=n;i++)f[i][0]=high[i];
45     for(int j=1;j<=21;j++){
46         tmp=n-(1<<j)+1;
47         for(int i=1,to;i<=tmp;i++){
48             to=i+(1<<(j-1));
49             if(f[i][j-1]<f[to][j-1])f[i][j]=f[i][j-1];
50             else f[i][j]=f[to][j-1];
51         }
52     }
53 }
54 int query(int l,int r){
55     int t=log(r-l+1)/log(2);
56     return min(f[l][t],f[r-(1<<t)+1][t]);
57 }
58 int lcp(int i,int j){
59     if(rk[i]>rk[j])swap(i,j);
60     return query(rk[i],rk[j]-1);
61 }
62 void Getanswer(){
63     int t,pp=n>>1;
64     for(int L=1;L<=pp;L++){
65         if(n%L)continue;
66         t=lcp(1,1+L);
67         if(t==n-L){
68             printf("%d\n",n/L);
69             return ;
70         }
71     }
72     printf("1\n");
73 }
74 void work(){
75     n=strlen(S+1);
76     for(int i=1;i<=n;i++)s[i]=S[i]-'A'+1;
77    Getsa();Gethight();prework();
78     Getanswer();
79 }
80 int main()
81 {
82     freopen("powerstrings.in","r",stdin);
83     freopen("powerstrings.out","w",stdout);
84     while(scanf("%s",S+1)){
85         if(S[1]=='.')break;
86         work();
87     }
88     return 0;
89 }
80分后缀数组

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 const int N=1e6+5;
 9 int net[N],n;char s[N];
10 void work(){
11     n=strlen(s+1);int t;
12     net[1]=1;
13     for(int i=2;i<=n;i++){
14         t=net[i-1];
15         while(t!=1 && s[t]!=s[i])
16             t=net[t-1];
17         if(s[t]==s[i])net[i]=t+1;
18         else net[i]=1;
19     }
20     if(!(n%(n-net[n]+1)))
21     printf("%d\n",n/(n-net[n]+1));
22     else printf("1\n");
23 }
24 int main()
25 {
26     freopen("powerstrings.in","r",stdin);
27     freopen("powerstrings.out","w",stdout);
28     while(scanf("%s",s+1)){
29         if(s[1]=='.')break;
30         work();
31     }
32     return 0;
33 }
AC KMP

 

posted @ 2017-07-14 21:20  PIPIBoss  阅读(453)  评论(0编辑  收藏  举报