ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)

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.

<b< dd="">

Output

For each s you should print the largest n such that s = a^n for some string a. 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.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3

求最大循环长度。

KMP可以求,之前做过,见。

http://www.cnblogs.com/hua-dong/p/8016873.html

http://www.cnblogs.com/hua-dong/p/8016916.html

这里实现了后缀数组(不过好像被卡了,只能同KMP实现)。

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
int min(int x,int y) { if(x<y) return x;return y;}
using namespace std;
const int maxn=1000010;
char ch[maxn];
struct SA
{
    int Rank[maxn],sa[maxn],tsa[maxn],A[maxn],cntA[maxn],B[maxn],cntB[maxn];
    int ht[maxn],Min[maxn][30],N;
    void get_SA()
    {
        N=strlen(ch+1);
        for(int i=0;i<=300;i++) cntA[i]=0;
        for(int i=1;i<=N;i++)  cntA[ch[i]]++;
        for(int i=1;i<=300;i++) cntA[i]+=cntA[i-1];
        for(int i=N;i>=1;i--)  sa[cntA[ch[i]]--]=i;
        Rank[sa[1]]=1;
        for(int i=2;i<=N;i++)  Rank[sa[i]]=Rank[sa[i-1]]+(ch[sa[i]]==ch[sa[i-1]]?0:1);
        for(int l=1;Rank[sa[N]]<N;l<<=1){
            for(int i=1;i<=N;i++) cntA[i]=cntB[i]=0;
            for(int i=1;i<=N;i++) cntA[A[i]=Rank[i]]++;
            for(int i=1;i<=N;i++) cntB[B[i]=i+l<=N?Rank[i+l]:0]++;
            for(int i=1;i<=N;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
            for(int i=N;i>=1;i--) tsa[cntB[B[i]]--]=i;
            for(int i=N;i>=1;i--) sa[cntA[A[tsa[i]]]--]=tsa[i];
            Rank[sa[1]]=1;
            for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]]?0:1);
        }
    }
    void get_hgt()
    {
        for(int i=1,j=0;i<=N;i++){
            if(j) j--;
            while(ch[i+j]==ch[sa[Rank[i]-1]+j]) j++;
            ht[Rank[i]]=j;
        }
    }
    void get_rmq()
    {
        for(int i=1;i<=N;i++) Min[i][0]=ht[i];
        for(int i=1;(1<<i)<=N;i++)
         for(int j=1;j+(1<<i)-1<=N;j++){
              Min[j][i]=min(Min[j][i-1],Min[j+(1<<(i-1))][i-1]);
         }
    }
    int query_rmq(int L,int R)
    {
        if(L>R) swap(L,R);L++;
        int k=log2(R-L+1);
        return min(Min[L][k],Min[R-(1<<k)+1][k]);
    }
    void solve()
    {
        int ans=1;
        for(int i=1;i<=N;i++){
            if(N%i!=0) continue;
            if(i+query_rmq(Rank[1],Rank[1+i])==N) {
                ans=N/i; break;
            }
        }   printf("%d\n",ans);
    }
}Sa;
int main()
{
    while(~scanf("%s",ch+1)){
        if(ch[1]==‘.‘) return 0;
        Sa.get_SA();
        Sa.get_hgt();
        Sa.get_rmq();
        Sa.solve();
    }  return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/8151272.html

时间: 2024-12-31 05:34:24

ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)的相关文章

(KMP 1.4)hdu 3746 Cyclic Nacklace(使用next数组来求循环节的长度——求一个字符串需要添加多少个字符才能使该字符串的循环节的个数&gt;=2)

题目: Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3387    Accepted Submission(s): 1549 Problem Description CC always becomes very depressed at the end of this month, he has che

POJ2406 Power Strings(KMP,后缀数组)

这题可以用后缀数组,KMP方法做 后缀数组做法开始想不出来,看的题解,方法是枚举串长len的约数k,看lcp(suffix(0), suffix(k))的长度是否为n- k ,若为真则len / k即为结果. 若lcp(suffix(0), suffix(k))的长度为n- k,则将串每k位分成一段,则第1段与第2段可匹配,又可推得第2段与第3段可匹配……一直递归下去,可知每k位都是相同的,画图可看出匹配过程类似于蛇形. 用倍增算法超时,用dc3算法2.5秒勉强过. #include<cstdi

SPOJ题目687 Repeats(后缀数组+RMQ求重复次数最多的子串的重复次数)

REPEATS - Repeats no tags A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string s = abaabaabaaba is a (4,3)-repeat with t = aba as its seed string. That is, the

URAL 1297 后缀数组:求最长回文子串

思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. 然后看题解,里面都是用RMQ先预处理任意两个后缀的最长公共前缀,因为不太知道这个,所以又看了一下午,嘛嘛-- 然后理解RMQ和后缀一起用的时候才发现其实这里不用RMQ也可以,只要特殊处理一下上面这个没过的例子就行了,哈哈--机智-- 不过那个国家集训队论文里面正解是用RMQ做的,自己还得会和RMQ一

Uva 12012 Detection of Extraterrestrial 求循环节个数为1-n的最长子串长度 KMP

题目链接:点击打开链接 题意: 给定一个字符串str 求字符串str的 循环节个数为 1-len 个的 最长子串长度 思路:套用kmp的性质 #include<string.h> #include<stdio.h> #include <iostream> using namespace std; #define n 1300 void getnext(char str[n],int next[n]){ int m=strlen(str); next[0]=next[1]

【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=1770 题解:一开始理解错题意,以为是abcxxxcba(xxx为v),开心地打了后缀数组后发现哎样例不对丫.. UVA的意思是abcxxxabc(xxx为v). 类似poj3693,我们暴

POJ 2774 后缀数组:求最长公共子串

思路:其实很简单,就是两个字符串连接起来,中间用个特殊字符隔开,然后用后缀数组求最长公共前缀,然后不同在两个串中,并且最长的就是最长公共子串了. 注意的是:用第一个字符串来判断是不是在同一个字符中,刚开始用了第二个字符的长度来判断WA了2发才发现. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<

POJ 1226后缀数组:求出现或反转后出现在每个字符串中的最长子串

思路:这题是论文里的最后一道练习题了,不过最后一题竟然挺水的. 因为求的是未反转或者反转后,最长公共子串. 刚开始还真不知道怎么构建连接成一个字符串,因为需要有反转嘛! 但是其实挺简单的,把未反转的和反转后的字符串都连起来,中间用未出现过的字符隔开就行了!然后未反转的和反转的在同一组. 二分枚举最长的公共前缀长度,然后统计看看这个最长的长度在不在所有的组里,如果在就符合-- #include<iostream> #include<cstdio> #include<cstrin

SPOJ 694、705 后缀数组:求不同子串

思路:这题和wikioi 1306一样,也都是求的不同子串的个数,但是wikioi 时间比较长,然后用Trie树就过了.但是我用那个代码提交这题的时候就WA了,比较晕--因为这题有多组样例,所以超了点时间. 所以这题当然就是用后缀数组做的啦! 算法分析: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照suffix(sa[1]),suffix(sa[2]),suffix(sa[3]),--,suffix(sa[n])的顺序计算,不难发现,对于每