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);
        }
    }
}
posted @ 2012-04-25 07:20  Because Of You  Views(519)  Comments(0Edit  收藏  举报