zoukankan      html  css  js  c++  java
  • [算法 笔记]字符串移位包含问题

      问题出自《编程之美》3.1 

      1 /* 2013.6.25
      2  * 问题:给定两个字符串s1和s2,要求判定给定字符串s2是否
      3  * 能够通过字符串s1循环移位得到的字符串包含。
      4  * 例如:
      5  * 1. s1 = AABCD,s2 = CDAA,则返回true;
      6  * 2. s1 = ABCD,s2 = ACBD,则返回false
      7  */
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <stdlib.h>
     11 
     12 enum { true = 1, false = 0 };
     13 
     14 /* 2013.6.25
     15  * 方式1:用s2[0]将字符串s1分为两个部分。
     16  * 第一部分:strcmp(s2, s1 + j, strlen(s1)-j) ,其中,j是s2[0] == s1[j]
     17  * 第二部分:strcmp(s2 + strlen(s1) - j, s1, strlen(s2) - strlen(s1) - j).
     18  * 时间复杂度:O( strlen(s1) * strlen(s2) ), 空间复杂度:O(1)
     19  */
     20 int CheckRotStr1( const char *s1, const char *s2 )
     21 {
     22     int start = 0;
     23     int nlen1, nlen2, tmpLen;
     24 
     25     if ( s1 == NULL || s1[0] == ''
     26         || s2 == NULL || s2[0] == '' )
     27     {
     28         printf( "Error for arguments!
    " );
     29         return -1;
     30     }
     31 
     32     // 查找s2[0]在s1中的位置
     33     nlen1 = strlen( s1 );
     34     nlen2 = strlen( s2 );
     35     while ( start < nlen1 )
     36     {
     37         if ( s2[0] == s1[start] )
     38             break;
     39 
     40         ++start;
     41     }
     42 
     43     if ( start == nlen1 )
     44         return false;
     45 
     46     tmpLen = nlen1 - start;
     47     if ( strncmp( s2, s1 + start, tmpLen ) == 0 )
     48     {
     49         if ( tmpLen == nlen2 )
     50             return true;
     51 
     52         start = tmpLen;
     53         tmpLen = nlen2 - tmpLen;
     54         if ( strncmp( s2 + start, s1, tmpLen ) == 0 )
     55             return true;
     56     }
     57 
     58     return false;
     59 }
     60 
     61 /* 2013.6.25
     62  * 方式2:拷贝一份s1填充到s1后面,然后查找s2是否为s1的子串。
     63  * 时间复杂度:O(strlen(s2)*strlen(s1)), 空间复杂度:O(2*strlen(s1))
     64  */
     65 int CheckRotStr2( const char *s1, const char *s2 )
     66 {
     67     char *newS1 = NULL;
     68     int nlen1, nlen2, start = 0;
     69 
     70     if ( s1 == NULL || s1[0] == ''
     71         || s2 == NULL || s2[0] == '' )
     72     {
     73         printf( "Error for arguments!
    " );
     74         return -1;
     75     }
     76 
     77     nlen1 = strlen( s1 );
     78     nlen2 = strlen( s2 );
     79     newS1 = (char *) malloc( nlen1 * 2 * sizeof( char ) + 1 );
     80     if ( newS1 == NULL )
     81     {
     82         printf( "Error for malloc!
    " );
     83         return -1;
     84     }
     85 
     86     // 拷贝字符串s1
     87     strncpy( newS1, s1, nlen1 );
     88     strncpy( newS1 + nlen1, s1, nlen1 );
     89     nlen1 <<= 1;
     90     newS1[nlen1] = '';
     91 
     92     // 查找s2[0]在newS1中的位置
     93     while ( start < nlen1 )
     94     {
     95         if ( s2[0] == newS1[start] )
     96             break;
     97 
     98         ++start;
     99     }
    100 
    101     if ( start == nlen1 )
    102         return false;
    103 
    104     if ( strncmp( s2, newS1 + start, nlen2 ) == 0 )
    105     {
    106         free( newS1 );
    107         return true;
    108     }
    109 
    110     free( newS1 );
    111     return false;
    112 }
    113 
    114 /* 2013.6.25
    115  * 方式3:思路和方式2一样,但是利用摩计算来省略拷贝问题
    116  * 时间复杂度:O(strlen(s2)+strlen(s1)), 空间复杂度:O(1)
    117  */
    118 int CheckRotStr3( const char* s1, const char *s2 )
    119 {
    120     int nlen1, nlen2, start = 0;
    121     int end, i = 0;
    122 
    123     if ( s1 == NULL || s1[0] == ''
    124         || s2 == NULL || s2[0] == '' )
    125     {
    126         printf( "Error for arguments!
    " );
    127         return -1;
    128     }
    129 
    130     nlen1 = strlen( s1 );
    131     nlen2 = strlen( s2 );
    132 
    133     // 查找s2[0]在newS1中的位置
    134     while ( start < nlen1 )
    135     {
    136         if ( s2[0] == s1[start] )
    137             break;
    138 
    139         ++start;
    140     }
    141 
    142     if ( start == nlen1 )
    143         return false;
    144 
    145     end = start + nlen1;
    146     // 需要注意,如果nlen2超过nlen1的长度,则返回false。
    147     while ( start < end && i < nlen2 )
    148     {
    149         int tmp = start % nlen1; // 利用摩计算消除了拷贝的需求
    150 
    151         if ( s2[i] != s1[tmp] )
    152             break;
    153 
    154         ++start;
    155         ++i;
    156     }
    157 
    158     if ( i == nlen2 )
    159         return true;
    160 
    161     return false;
    162 }
    163 
    164 /* 2013.6.25
    165  * 以上三个函数在简单模式下成立。但是还是存在错误。
    166  */
    167 
    168 /* 2013.6.25
    169  * 本次采用的是方式2,然后使用KMP来进行子串匹配。
    170  * KMP算法来自博客 算法之道
    171  * 网址:http://blog.csdn.net/v_july_v/article/details/7041827#comments
    172  */
    173 int CheckRotStrOpt( const char *s1, const char *s2)
    174 {
    175     int nlen1, nlen2;
    176     int *overlay_value = NULL;
    177     char* newS1 = NULL;
    178     int index = 0;
    179     int i, j, ret = false;
    180 
    181     if ( s1 == NULL || s1[0] == ''
    182         || s2 == NULL || s2[0] == '' )
    183     {
    184         printf( "Error for arguments.
    " );
    185         return -1;
    186     }
    187 
    188     nlen1 = strlen( s1 );
    189     nlen2 = strlen( s2 );
    190 
    191     newS1 = (char *) malloc( nlen1 * 2 * sizeof( char ) + 1 );
    192     if ( newS1 == NULL )
    193     {
    194         printf( "Error for malloc!
    " );
    195         return -1;
    196     }
    197 
    198     // 拷贝字符串s1
    199     strncpy( newS1, s1, nlen1 );
    200     strncpy( newS1 + nlen1, s1, nlen1 );
    201     nlen1 <<= 1;
    202     newS1[nlen1] = '';
    203 
    204     overlay_value = (int *) malloc( nlen2 * sizeof(int) );
    205     if ( overlay_value == NULL )
    206     {
    207         printf( "Error for malloc.
    " );
    208         free( newS1 );
    209         return -1;
    210     }
    211     overlay_value[0] = -1;
    212 
    213     // nextArray
    214     for ( i = 1; i < nlen2; ++i )
    215     {
    216         index = overlay_value[i - 1];
    217         while ( index >= 0 && s2[index + 1] != s2[index] )
    218         {
    219             index = overlay_value[index];
    220         }
    221 
    222         if ( s2[index + 1] == s2[index] )
    223             overlay_value[i] = index + 1;
    224         else
    225             overlay_value[i] = -1;
    226     }
    227 
    228     i = 0, j = 0;
    229     while ( i < nlen2 && j < nlen1 )
    230     {
    231         if ( newS1[j] == s2[i] )
    232         {
    233             ++i;
    234             ++j;
    235         }
    236         else if ( i == 0 )
    237         {
    238             ++j;
    239         }
    240         else
    241         {
    242             i = overlay_value[i - 1] + 1;
    243         }
    244     }
    245 
    246     if ( i == nlen2 )
    247         ret = true;
    248 
    249     free( newS1 );
    250     free( overlay_value );
    251 
    252     return ret;
    253 }
    254 
    255 int main()
    256 {
    257     char* str10 = "AABCDA";
    258     char* str11 = "ABCD";
    259     char* str20 = "CDAA";
    260     char* str21 = "ACBD";
    261     int ret = 0;
    262 
    263     ret = CheckRotStrOpt( str10, str20 );
    264     printf( "The result is %d.
    ", ret );
    265 
    266     ret = CheckRotStrOpt( str11, str21 );
    267     printf( "The result is %d.
    ", ret );
    268 
    269     return 0;
    270 }
    View Code

      

  • 相关阅读:
    vue(5)联动+tab页
    vue(4)hello world
    vue(3)IDE
    vue(2)创建项目
    vue(1)安装
    线程池(6)简单创建线程3种实现
    logback日志简记
    [省选前集训2021] 模拟赛2
    无标号无根树计数
    [省选前集训2021] 模拟赛1
  • 原文地址:https://www.cnblogs.com/life91/p/3154101.html
Copyright © 2011-2022 走看看