1. 程式人生 > >Power Strings---字串hash

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;
}