题解 UVA10298 【Power Strings】

解法:

其实用很普通的“自然溢出法的Hash”就可以过这道题目(ps:出题人真良心没有故意卡我的Hash)。首先我们先枚举字串的长度length_k,之后我们在找出每个长度为length_k的字串,用Hash判断一下这些字串是否相同就可以了。时间复杂度:
\[ O (n/1+n/2+n/3+\cdots+n/n)\approx O(n)\]

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e6+5;
const int Base = 31;

char s[N];
unsigned long long Hash[N];
unsigned long long power[N]; //power[i]=base^i;

int main(){
    power[0]=1;
    for(int i=1;i<N;i++) power[i]=power[i-1]*Base;
    while(true){
        scanf("%s",s);
        if(s[0]=='.') break;
        int length=strlen(s); //获取字符串的长度
        Hash[0]=0;Hash[1]=(unsigned long long)s[0];
        for(int i=2;i<=length;i++) Hash[i]=Hash[i-1]*Base+(unsigned long long)s[i-1]; //计算Hash值
        for(int length_k=1;length_k<=length;length_k++){ //枚举可能匹配的长度
            if(length%length_k!=0) continue;
            unsigned long long t; //用于储存上一个k
            bool flag=true;
            for(int i=length_k;i<=length;i+=length_k){ //枚举起点
                unsigned long long k=Hash[i]-Hash[i-length_k]*power[length_k];
                if(i!=length_k){
                    if(t!=k){
                        flag=false;
                        break;
                    }
                }
                t=k;
            }
            if(flag){
                printf("%d\n",length/length_k);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lixiao189/p/9300693.html