Common Divisors 【CodeForces - 182D】【KMP~读错题意WA半天】

我的KMP学习日记

题目链接


题意:

  看题意我以为它是要我求的是两个字符串的最小周期的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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值