【编程之美】字符串移位包含的问题(续)

简介:

问题描述

给定两个字符串s1和s2,要求判定s2是否能被s1循环移位(rotate)得到的字符串包含。例如,给定字符串s1=AABCD和s2=CDAA,返回true;给定s1=ABCD和s2=ACBD返回false。

对问题的两种分析,详见:http://www.cnblogs.com/bigwangdi/archive/2013/05/23/3095507.html

思路一 是暴力算法,穷举所有最后还不一定找到。

思路二 使用空间换取时间,是一种很好的思路。下面给出另外两个思路:

思路三 思路二的优化。增加和源字串产度相同的空间,其实在大部分情况下造成浪费,可以根据待查字串动态分配指定的空间。如图:

代码

复制代码
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
    char a[] = "012345";
    char b[] = "45012";
    int i, j;
    int lenc = strlen(a) + strlen(b) - 1;
    char *c = (char*)malloc(sizeof(char) * lenc);
    strcat(c, a);
    for(i=0; i<strlen(b)-1; i++)
        c[strlen(a)+i] = a[i];
    printf("%s\n", c);
    if(strstr(c, b))
        printf("Yes!\n");
    else
        printf("No!\n");
    free(c);
    return 0;

}
复制代码

结果:     0123450123

              Yes!

思路四

    首先看个子问题:

问题描述      平移abc123,是结果为123abc

      可以注意旋转平移——浪费时间

      可以用备用数组暂存——浪费空间

      优化:翻转函数rev(),例如:rev(abc) = cba;

              那么rev(abc123) = rev(rev(abc)rev(123)) = rev(cba321)= 123abc

对于原始字串abcdef,旋转后,观察规律(如下),可以看出如果

复制代码
fabcde
efabcd
defabc
cdefab
bcdefa
复制代码

 可以看出首尾字符起决定作用,可以根据待查字串找出旋转元素的个数,然后旋转源字串,判断待查字串是否在源字串中。如图:

 

代码:

复制代码
#include <stdio.h>
#include <string.h>
char swap(char *a, int begin, int end)
{
    int i,j;
    char tmp;
    for(i=begin,j=end; i<j; i++,j--)
    {
        tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}

int main()
{
    char c[] = "abcdef";
    char aim[] = "fab";
    char *p;
    int lens;
    p = strstr(c, aim);
    if(p)
    {
        printf("Yes, it's a part\n");
        return 0;
    }
    if(strlen(c) < strlen(aim))
    {
        printf("No, it's not a part!\n");
        return -1;
    }
    if(strlen(c) == 1)
    {
        printf("No, it's not a part\n");
        return -1;
    }
    char token[2] = {c[strlen(c)-1], c[0]};
    p = strstr(aim, token);
    while(p)
    {
        lens = p - aim + 1;
        swap(c, 0, strlen(c)-1-lens);
        swap(c, strlen(c)-lens, strlen(c)-1);
        swap(c, 0, strlen(c)-1);
        if (strstr(c, aim))
        {
            printf("Yes, it is a part\n");
            return 0;
        }
        p = strstr(p+1, token); //注意其中有诈,有可能之前找到的并不是首尾字串而是其中的一部分。
    }
    printf("No, it's not a part\n");
    return 0;
}
复制代码

结果:Yes, it is a part




本文转自jihite博客园博客,原文链接:http://www.cnblogs.com/kaituorensheng/archive/2013/06/01/3105042.html,如需转载请自行联系原作者

相关文章
|
7月前
|
Java 测试技术 Python
每日一题《剑指offer》字符串篇之表示数值的字符串
每日一题《剑指offer》字符串篇之表示数值的字符串
48 0
每日一题《剑指offer》字符串篇之表示数值的字符串
【每日挠头算法(4)】字符串相加|字符串相乘
【每日挠头算法(4)】字符串相加|字符串相乘
|
算法 C语言
【基础算法】浅浅刷个小题 # 移动零 # 丢失的数字 # 转换成小写字母 # 和为零的N个不同整数 # 猜数字 #
【基础算法】浅浅刷个小题 # 移动零 # 丢失的数字 # 转换成小写字母 # 和为零的N个不同整数 # 猜数字 #
每日一题,数组字符串的匹配问题
每日一题,数组字符串的匹配问题
|
存储 机器学习/深度学习
母牛的故事 替换空格 二进制中1的个数 不使用第三个变量交换a,b的值
母牛的故事 替换空格 二进制中1的个数 不使用第三个变量交换a,b的值
87 0
剑指offer 19. 表示数值的字符串
剑指offer 19. 表示数值的字符串
41 0
【基础算法】浅浅刷个小题 # 找不同 # 字符串中的单词数 # 重新排列字符串 #
【基础算法】浅浅刷个小题 # 找不同 # 字符串中的单词数 # 重新排列字符串 #
【每日一题Day41】生成交替二进制字符串的最小操作数 | 模拟 位运算
思路:长度一定的交替二进制字符串有两种可能性,以字符0开头的0101字符串和以字符1开头的1010字符串,因此只需要将字符串s与这两种字符串进行比较,记录不相同的字符个数,最后返回较小值即可
100 0
【每日一题Day41】生成交替二进制字符串的最小操作数 | 模拟 位运算
|
算法
每日算法刷题Day9-字符串移位包含问题、字符串乘方
⭐每日算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,与笔者另一系列文章有所区别,并不是以知识点的形式提升算法能力,而是以实战习题的形式理解算法,使用算法。
258 0
每日算法刷题Day9-字符串移位包含问题、字符串乘方