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

问题描述

给定两个字符串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

 

posted @ 2013-06-01 12:43  jihite  阅读(948)  评论(0编辑  收藏  举报