Power Strings---字符串hash

问题 C: 【哈希和哈希表】Power Strings

时间限制: 1 Sec  内存限制: 128 MB
提交: 38  解决: 18
[提交] [状态] [讨论版] [命题人:外部导入]

题目描述

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).

输入

 Each test case is a line of input representing s, a string of printable characters.

输出

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

样例输入

abcd
aaaa
ababab
.

样例输出

1
4
3

让你求,嗯,这个串是由最多多少个相同的小字符串构成的,

例如aaaa,可以使1个aaaa组成,也可以是两个aa,也可以是四个a

那么输出4,即最多几个

那么从最小的长度i = 1开始枚举,只有strlen(a)%i==0,才能恰好组成,否则跳过即可

对于%==0的情况暴力切割出所有的子串(事先hash),判断能否成立,

一旦出现成立,那么就是答案,

还有明显枚举到strlen(a)/2,即可,因为再往后枚举,都不成立的

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int maxn = 1e6+7;
const pll k{1e9+9,1e9+7},p{1e9+7,1e9+9},one{1ll,1ll},zero{0ll,0ll};
pll operator - (pll a,pll b){return make_pair((a.first - b.first + p.first)%p.first,(a.second - b.second + p.second)%p.second);}
pll operator * (pll a,pll b){return make_pair((a.first * b.first)%p.first,(a.second * b.second)%p.second);}
pll operator + (pll a,pll b){return make_pair((a.first + b.first)%p.first,(a.second + b.second)%p.second);}
pll operator + (pll a,int b){return make_pair((a.first + b)%p.first,(a.second + b)%p.second);}
pll Hash(char a[],int len){
    pll ans = zero;
    for(int i=0;i<len;i++)
        ans = ans*k + a[i];
    return ans;
}
pll Pow(pll a,int n){
    pll ans = one;
    while(n){
        if(n&1)ans = ans*a;
        a = a*a;
        n>>=1;
    }
    return ans;
}
char a[maxn];
pll Len[maxn];
int main(){
    while(cin>>a+1){
        if(a[1]=='.')break;
        Len[0] = zero;
        for(int i=1;a[i];i++){
            Len[i] = Len[i-1]*k + a[i];
        }
        int ans = 1,la = (strlen(a+1)+1)/2,ln = strlen(a+1);
        for(int i=1;i<=la;i++){
            if(ln%i)continue;///一个优化
            int flag = 0;
            for(int j=i;!flag && j<=ln;j+=i)
                if(Len[j]-Len[j-i]*Pow(k,i)!=Len[i])
                    flag = 1;
            if(!flag){
                ans = ln/i;
                break;///找到即跳出
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Du_Mingm/article/details/83378151
今日推荐