POJ 2406Power Strings (dc3 后缀数组)

来源:互联网 发布:社交软件英文怎么说 编辑:程序博客网 时间:2024/06/07 05:29
Power Strings
Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 50961 Accepted: 21273

Description

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcdaaaaababab.

Sample Output

143

Hint

This problem has huge input, use scanf instead of cin to avoid time limit exceed.

Source

Waterloo local 2002.07.01
题意:求一个字符串最多循环次数
想法:
倍增后缀数组超时
dc3后缀数组刚好能过,最好用kmp做
代码:
#include <cstdio>#include <cstring>#include <algorithm>#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))#define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)using namespace std;const int N = 1000005;int wa[N], wb[N], ws[N], wv[N], sa[N * 3];int rank[N * 3], height[N * 3], s[N], n;char str[N];int c0(int *r, int a, int b){    return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];}int c12(int k, int *r, int a, int b){    if (k == 2)        return r[a] < r[b] || r[a] == r[b] && c12(1, r, a + 1, b + 1);    return r[a] < r[b] || r[a] == r[b] && wv[a + 1] < wv[b + 1];}void sort(int *r, int *a, int *b, int n, int m){    for (int i = 0; i < n; i++) wv[i] = r[a[i]];    for (int i = 0; i < m; i++) ws[i] = 0;    for (int i = 0; i < n; i++) ws[wv[i]]++;    for (int i = 1; i < m; i++) ws[i] += ws[i - 1];    for (int i = n - 1; i >= 0; i--) b[--ws[wv[i]]] = a[i];}void dc3(int *r, int *sa, int n, int m){    int i, j, *rn = r + n, *san = sa + n, ta = 0, tb = (n + 1) / 3, tbc = 0, p;    r[n] = r[n + 1] = 0;    for (i = 0; i < n; i++)        if (i % 3 != 0) wa[tbc++] = i;    sort(r + 2, wa, wb, tbc, m);    sort(r + 1, wb, wa, tbc, m);    sort(r, wa, wb, tbc, m);    for (p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; i++)        rn[F(wb[i])] = c0(r, wb[i - 1], wb[i]) ? p - 1 : p++;    if (p < tbc) dc3(rn, san, tbc, p);    else for (i = 0; i < tbc; i++) san[rn[i]] = i;    for (i = 0; i < tbc; i++) if (san[i] < tb) wb[ta++] = san[i] * 3;    if (n % 3 == 1) wb[ta++] = n - 1;    sort(r, wb, wa, ta, m);    for (i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i;    for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++)        sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];    for (; i < ta; p++) sa[p] = wa[i++];    for (; j < tbc; p++) sa[p] = wb[j++];}void calheight(int *r, int *sa, int n){    int i, j, k = 0;    for (i = 1; i <= n; i++) rank[sa[i]] = i;    for (i = 0; i < n; height[rank[i++]] = k)        for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++);}int main(){    while (scanf("%s", str) == 1 && str[0] != '.')    {        int len = strlen(str);        for (int i = 0; i < len; i++)            s[i] = str[i] - 'a' + 1;        s[len] = 0;        dc3(s, sa, len + 1, 105);        calheight(s, sa, len);        int flag = 0;        for (int i = 1; i <= len; i++)        {            if (len % i == 0 && rank[0] == rank[i] + 1 && height[rank[0]] == len - i)            {                printf("%d\n", len / i);                flag = 1;                break;            }        }        if (!flag)            printf("1\n");    }    return 0;}
代码二:
kmp(next数组)快速求
#include <stdio.h>#include <string.h>int next[1000005];char str[1000005];void getnext(char str[]){    int i =1,j =0;    int len = strlen(str);    next [0] = -1;    while(i <len)    {        if(j == -1 || str[i] == str[j])        {            i++;            j++;            next[i] = j;        }        else            j = next[j];    }}int main(){    while(gets(str+1))    {        if(str[1]=='.') break;       memset(next,0,sizeof(next));      if(str[1]=='\0')      {          printf("0\n");          continue;      }      int len=strlen(str+1);      getnext(str+1);      int ans=1;      int i;      if(len%(len-next[len])==0)            ans=len/(len-next[len]);       printf("%d\n",ans);    }    return 0;}



原创粉丝点击