哈希-poj2406(每个字符串最小周期的个数)

先建立字符串的哈希数组

枚举每个子串

********************************************************************

建立基数数组 函数

void fbase()
{
    base[0]=1;
    for(int i=1;i<maxn;i++)
    base[i]=base[i-1]*m;
}

建立字符串哈希数组

void makehashe(char s[])
{
    hashe[len]=0;
    for(int i=len-1;i>=0;i--)
    hashe[i]=hashe[i+1]*m+s[i];
}

 枚举+判断

for(int i=1;i<=len;i++)//字符串长度每次增加一,判断是否为周期
        {
            if(len%i!=0)
            continue;//循环节的长度必须要能整除总长度len
            ull temp=hashe[0]-hashe[i]*base[i];//temp为长度增加一后,串的哈希值
            int j=0;
            for(j=i;j<=len;j+=i)//每次后移子串的长度 
                if(temp!=hashe[j]-hashe[j+i]*base[i])
                break;
            if(j==len)//如果每次跳跃都匹配 此子串即为周期串
            {
                n=len/i;
                break;
            }
        }

 代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef unsigned long long ull;
const int maxn=1000001;
char s[maxn];
ull base[maxn];
ull hashe[maxn];
ull m=23333;
int len;
void fbase()
{
    base[0]=1;
    for(int i=1;i<maxn;i++)
    base[i]=base[i-1]*m;
}
void makehashe(char s[])
{
    hashe[len]=0;
    for(int i=len-1;i>=0;i--)
    hashe[i]=hashe[i+1]*m+s[i];
}
int main()
{
    fbase();//建立基数数组
    while(scanf("%s",s))
    {
        if(strcmp(s,".")==0)
        break;
        len=strlen(s);
        int n=0;
        makehashe(s);//建立哈希数组
        for(int i=1;i<=len;i++)//字符串长度每次增加一,判断是否为周期
        {
            if(len%i!=0)
            continue;//循环节的长度必须要能整除总长度len
            ull temp=hashe[0]-hashe[i]*base[i];//temp为长度增加一后,串的哈希值
            int j=0;
            for(j=i;j<=len;j+=i)//每次后移子串的长度 
                if(temp!=hashe[j]-hashe[j+i]*base[i])
                break;
            if(j==len)//如果每次跳跃都匹配 此子串即为周期串
            {
                n=len/i;
                break;
            }
        }
        printf("%d\n",n);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xqx1343002589/article/details/81180332