PA12题解报告——循环移位(Cycle)

数据结构与算法实验2020夏第二批(中国石油大学)
PA12题解报告——循环移位(Cycle)(Schedule)

目录

  1. 题目描述
  2. 题目分析
  3. 编码实现

一、题目描述

1. 描述

所谓循环移位是指。一个字符串的首字母移到末尾, 其他字符的次序保持不变。比如ABCD经过一次循环移位后变成BCDA。
给定两个字符串,判断它们是不是可以通过若干次循环移位得到彼此。

2. 输入

由m行组成,每行包含两个由大写字母’A’~'Z’组成的字符串,中间由空格隔开。

3. 输出

对于每行输入,输出这两个字符串是否可以通过循环移位得到彼此:YES表示是,NO表示否。

4. 例
//输入
AACD CDAA
ABCDEFG EFGABCD
ABCD ACBD
ABCDEFEG ABCDEE
//输出
YES
YES
NO
NO
5. 限制

0 ≤ m ≤ 5000
1 ≤ |S1|, |S2| ≤ 10^5
时间:2 sec
内存:256 MB

二、题目分析

代码实现

读入两个字符串,如果两字符串长度不同,则直接输出No,否则,则把一个字符串接在其自身后面形成一个新串,然后查询另一个字符串是否是新串的子串,如果是则Yes,否则No。

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

三、编码实现

说明:
下述代码全部为【数据结构与算法实验 OJ 平台】提交过的代码。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define set(S, i) ( (S)[i] - 'A' )

bool Check(char* P, char* T, size_t i)
{
    for (size_t m = strlen(P), j = 0; j < m; j++, i++)
    {
        if (P[j] != T[i]) return false;
    }
    return true;
}

long long int Prepare(size_t m)
{
    long long int D = 1;
    for (size_t i = 1; i < m; i++)
        D = (D*30) % 1000;
    return D;
}

void Update(long long int& hashT, char* T, size_t m, size_t k, long long int D)
{
    hashT = (hashT - set(T, k - 1)*D) % 1000;
    hashT = (hashT*30 + set(T, k + m - 1)) % 1000;
    if (hashT < 0) hashT += 1000;
}

bool Matching(char* P, char* T)
{
    size_t m = strlen(P), n = strlen(T);
    long long int D, hashP = 0, hashT = 0;
    D = Prepare(m);
    for (size_t i = 0; i < m; i++)
    {
        hashP = (hashP*30 + set(P, i)) % 1000;
        hashT = (hashT*30 + set(T, i)) % 1000;
    }
    for (size_t k = 0;;)
    {
        if (hashT == hashP && Check(P, T, k)) return true;
        if (++k>n - m) return false;
        else Update(hashT, T, m, k, D);
    }
}

int main()
{
    char* p1 = (char*)malloc(sizeof(char)*(100010));
    char* p2 = (char*)malloc(sizeof(char)*(100010 * 2));

    do
    {
        if (scanf("%s %s", p1, p2) == EOF) break;
        int n1, n2;
        n1 = strlen(p1); n2 = strlen(p2);
        if (n1 != n2) printf("NO\n");
        else
        {
            int i;
            for (i = n2; i < n2 * 2 - 1; i++) p2[i] = p2[i - n2];
            p2[i] = '\0';

            if (Matching(p1, p2)) printf("YES\n");
            else printf("NO\n");
        }

    } while (1);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值