Kmp(求字符串公共循环节数目)——Common Divisors ( CodeForces 182D )

分析: 题意为给出两个字符串,求其公共循环节的数目,那么首先要求出其公共最小循环节!这里需要用到Kmp算法中的SetNext()函数来求循环节。

关键步骤: 1.SetNext()函数:(将第一个重复位之前的所有位的值赋为-1,然后第一个重复位从0开始,之后匹配失败也赋值为0) 

void SetNext(char s[])
{
        int j=-1,i;
        Next[0]=-1;
        int len=strlen(s);
        for(i=1;i<len;i++)
        {
            while(j>=0&&s[i]!=s[j+1])
                j=Next[j];
            if(s[i]==s[j+1])
                j++;
            Next[i]=j;
        }
}

2.求字符串最短循环节:(与上面SetNext函数一块用)

 void recycle (char s[])
    {
        int len = str(s);
        int length = 0;//最短循环节长度
        if(len % ( len - Next[len-1]-1 ) ==0)
            length = len - Next[len-1];
        else
            length = len;
        //创建最短循环节字符串
        for(int i=0;i<length;i++)
        {
            rec[i] = s[i];
        }

题解: 求出最短循环节长度length后,再求出原来两个字符串长度的最大公约数max,然后不断叠加length,直到length大于max,过程中如果叠加得到的结果能整除两个字符串长度就说明这也是一个公共循环节。

完整代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>

using namespace std;

char a[112345];
char b[112345];
char c[112345];

int Next[112345];
int M,N;
int NN;
int cc;
void SetNext(char s[])
{
        int j=-1,i;
        Next[0]=-1;
        int len=strlen(s);
        for(i=1;i<len;i++)
        {
            while(j>=0&&s[i]!=s[j+1])
                j=Next[j];
            if(s[i]==s[j+1])
                j++;
            Next[i]=j;
        }
}
void circle(char s[])
{
    cc=0;
    if( NN%(NN-Next[NN-1]-1) == 0 )
        cc = NN-Next[NN-1]-1;
    else
        cc = NN;
    for(int i=0;i<cc;i++)
        c[i] = s[i];

}

int Kmp(char x[],char y[])
{
    int cnt = 0;
    int i=0,j=0;
    while(i<N)
    {

        if(x[i]==y[j])
            i++, j++;
        else
            return -1;
        if(j==cc)
        {
            j = 0;
            cnt++;
        }
    }
    return cnt;
}

int gcd(int a, int b)
{
    return b==0? a : gcd(b, a%b);
}

int main()
{
    scanf("%s", a);
    scanf("%s", b);


    int tmp;
    if(strlen(a)>=strlen(b))
    {
        N = strlen(a);
        NN = strlen(b);
        SetNext(b);
        circle(b);
        tmp = Kmp(a, c);
    }
    else
    {
        N = strlen(b);
        NN = strlen(a);
        SetNext(a);
        circle(a);
        tmp = Kmp(b, c);
    }


    int ans=0;
    if(tmp>0)
    {
        int mm = gcd(N,NN);
        int d = cc;
        while(cc<=mm)
        {
            if( N%cc == 0 && NN %cc == 0)
            {
                ans++;
            }
            cc+=d;
        }
    }
    cout << ans << endl;
    return 0;
}

 

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/qq_40859951/article/details/82829086
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞