zoukankan      html  css  js  c++  java
  • [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/L);
    69             return ;
    70         }
    71     }
    72     printf("1
    ");
    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-net[n]+1));
    22     else printf("1
    ");
    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
  • 相关阅读:
    bzoj 1054
    bzoj 1047
    bzoj 2761
    bzoj 1191
    bzoj 2748
    bzoj_1003 物流运输
    新的开始( [USACO08OCT]打井Watering Hole)
    map
    Generic Cow Protests-G——60分做法
    逆序对
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7172291.html
Copyright © 2011-2022 走看看