Common Divisors 【CodeForces
阿新 • • 發佈:2018-12-17
題目連結
題意:
看題意我以為它是要我求的是兩個字串的最小週期的gcd(),後來WA了4發發現好像哪裡不大對,畢竟給的樣例也太特殊的,然後反覆讀題,終於讀懂它終於要幹嘛的了。。。。
題目讓我們求的是有幾個這樣的子字串,可以恰好的構成原來的這一對字串,例如“abcabc”與“abcabcabcabcabcabc”可以由"abc"組成也可以由"abcabc"組成,所以答案是個數2。嗚嗚嗚......
思路:
那麼,還是好做的,我們看到兩組字串,現求出各自的最小週期,這裡呢可以使用KMP()的next[]來做,求最小週期,然後比較兩個最小週期是否相等,不相等直接輸出"0"就是了,然後在看最小週期的倍數,是否能被原字串的長度整除,能的話就答案+1。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN=1e5+5; char a[maxN], b[maxN]; int lena, lenb, nex[maxN], las[maxN]; void cal_next_a() { nex[0] = nex[1] =0; int k = 0; for(int i=2; i<=lena; i++) { while(k>0 && a[k+1]!=a[i]) k=nex[k]; if(a[k+1] == a[i]) k++; nex[i]=k; } } void cal_nex_b() { las[0] = las[1] = 0; int k = 0; for(int i=2; i<=lenb; i++) { while(k>0 && b[k+1]!=b[i]) k=las[k]; if(b[k+1] == b[i]) k++; las[i]=k; } } bool check(int len) { for(int i=1; i<=len; i++) { if(a[i]!=b[i]) return false; } return true; } int gcd(int a, int b) { return b==0?a:gcd(b, a%b); } int main() { while(scanf("%s%s", a+1, b+1)!=EOF) { getchar(); lena = (int)strlen(a+1); lenb=(int)strlen(b+1); cal_next_a(); int tmp_a=lena-nex[lena]; int cycle_a=lena; if(lena%tmp_a==0) { cycle_a=tmp_a; tmp_a=lena/tmp_a; } else tmp_a=1; cal_nex_b(); int tmp_b=lenb-las[lenb]; int cycle_b=lenb; if(lenb%tmp_b==0) { cycle_b=tmp_b; tmp_b=lenb/tmp_b; } else tmp_b=1; if(cycle_a == cycle_b) { if(check(cycle_a)) { int ans=0; for(int i=cycle_a; i<=lena && i<=lenb; i+=cycle_a) { if(lena%i==0 && lenb%i==0) ans++; } printf("%d\n", ans); } else printf("0\n"); } else printf("0\n"); } return 0; }