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


    问题描述

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

     

  • 相关阅读:
    JS常用设计模式
    react native两次点击返回按钮退出APP
    react-native-device-info集成遇到的坑
    Django环境搭建之hello world
    jmeter之beanshell断言实例
    jmeter之beanshell断言---数据处理
    Jmeter将JDBC Request查询结果作为下一个接口参数方法(转载)
    App功能测试的注意点
    mybatis的CRUD实例(四)
    mybatis的CRUD实例(三)
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/3105042.html
Copyright © 2020-2023  润新知