• [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
  • 相关阅读:
    Linux 共享库
    使用Visual Studio(VS)开发Qt程序代码提示功能的实现(转)
    ZOJ 3469 Food Delivery(区间DP)
    POJ 2955 Brackets (区间DP)
    HDU 3555 Bomb(数位DP)
    HDU 2089 不要62(数位DP)
    UESTC 1307 windy数(数位DP)
    HDU 4352 XHXJ's LIS(数位DP)
    POJ 3252 Round Numbers(数位DP)
    HDU 2476 String painter (区间DP)
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7172291.html
Copyright © 2020-2023  润新知