codeforces 182D Common Divisors KMP做法
http://www.codeforces.com/problemset/problem/182/D
求两个字符串的公约数的个数,具体细节见题目
利用KMP可以求最小周期的特性来解这道题
具体证明参见我的另一篇文章
所以第一步:KMP求出两个串的最小周期 t1 t2
第二步:分情况讨论
1: t1==n&&t2==m
2: t1==n t2!=m
3: t1!=n t2==m
4: t1!=n&&t2!=m
View Code
#include<cstdio> #include<cstring> int n,m; char a[100100],b[100100]; int p1[100100]; int p2[100100]; void getp(int *p,char b[],int m){ p[1]=0; int i,j=0; for(i=2;i<=m;i++){ while(j>0&&b[j+1]!=b[i]) j=p[j]; if(b[j+1]==b[i]) j+=1; p[i]=j; } } inline int gcd(int a,int b){ return a==0?b:gcd(b%a,a); } int main() { int i; while(scanf("%s%s",a+1,b+1)!=EOF) { bool flag; n=strlen(a+1); m=strlen(b+1); getp(p1,a,n); getp(p2,b,m); int t1,t2; if(m%(m-p2[m])==0) t2=(m-p2[m]); else t2=m; if(n%(n-p1[n])==0) t1=(n-p1[n]); else t1=n; if(t1==n&&t2==m) { if(strcmp(a+1,b+1)==0) printf("%d\n",1); else printf("%d\n",0); } else if(t1==n) { if(t2==n) { flag=true; for(i=1;i<=n;i++) if(a[i]!=b[i]) flag=false; if(flag)printf("%d\n",1); else printf("0\n"); } else printf("0\n"); } else if(t2==m) { if(t1==m) { flag=true; for(i=1;i<=m;i++) if(a[i]!=b[i]) flag=false; if(flag) printf("%d\n",1); else printf("0\n"); } else printf("0\n"); } else { int ans=0; int lc=t1*t2/gcd(t1,t2); if(lc>n||lc>m) { printf("0\n"); continue; } bool flag=true; for(i=1;i<=lc;i++) if(a[i]!=b[i]) flag=false; if(!flag) { printf("0\n"); continue; } int tmp=lc; while(lc<=m&&lc<=n) { if(m%lc==0 && n%lc==0) ans++; lc+=tmp; } printf("%d\n",ans); } } }