c - 在另一个字符串中查找字符串的所有可能组合

时间:2014-07-13 07:07:00

标签: c

假设我有一个字符串“ron”。我需要在字符串中找到“ron”的所有组合,假设“ xxxxxxronxxxxnorxxxxxrno ”。输出应该是ron,也不是在字符串中找到rno。

这样做的一种方法是首先生成“ron”的所有组合,然后使用类似

之类的内容检查原始字符串中的这些子字符串。
#include<stdio.h>
#include<string.h>

int count, occur; 
char *str[100];

/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

/* Function to print permutations of string
   This function takes three parameters:
   1. String
   2. Starting index of the string
   3. Ending index of the string. */
void permute(char *a, int i, int n) 
{
   int j; 
   if (i == n)
     //printf("%s\t", a);
     {
        str[count++]=a;
        printf("%s\t", str[count-1]);
     }    

   else
   {
        for (j = i; j <= n; j++)
       {
          swap((a+i), (a+j));
          permute(a, i+1, n);
          swap((a+i), (a+j)); //backtrack
       }
   }
} 

void substring(char *b, int i)
{
    char *tmp = b;
    while(tmp = strstr(tmp, str[i]))
    {
       occur++;
       tmp++;
    }
}

/* Driver program to test above functions */
int main()
{
   char a[] = "ABC";
   char b[] = "ABCRTYBACXCAB";    
   int i;

   count=0;
   occur=0;

   permute(a, 0, 2);

   for(i=0;i<count;i++)
      printf("%s\t", str[i]);

   for(i=0;i<count;i++)
      substring(b,i);

   printf("\nOccurences: %d", occur);

   return 0;
}

当我执行此操作时,输出为:

ABC ACB BAC BCA CBA CAB

ABC ABC ABC ABC ABC ABC

出现:6

在permute中str的值正确显示,但为什么它们在main中有所不同? 出了什么问题?

解决:

STR [计数++] =的strdup(a)的

将* str []转换为str [] []然后执行strcpy(str [],a)

2 个答案:

答案 0 :(得分:1)

首先为所有"ron"排列设置Aho-Corasick状态机(这是很好的练习)然后将此计算机应用到第二个字符串。这是非常有效的解决方案,简短的第一个字符串。

编辑:我已经意识到Aho-Corasick状态机需要N!内部状态,无论如何都会将其炸毁。必须构造一些具有压缩状态的其他类型的状态机。到目前为止,我正在思考找到的子字符串的链表,其中哈希表或线性表指向每个部分。

Edit2 :存在O(N+M)时间和O(A)空间复杂度的解决方案,其中NM是输入字符串和{{的大小1}}是GitHubGist上字母的大小。它使用位图来跟踪属于子列表的字符,以及在字符串和后向引用指针中找到的字符,其中每个字符到目前为止都找到了。在64位平台上,ASCII的所有状态大小都是2128,非常适合现代硬件的L1 CPU缓存。

答案 1 :(得分:1)

以下是非常一般......

  char test[] = "xxxronronronxxx" ;
  const char* s ;

  s = test ;

  const char* seek = "ron" ;
  int count = 0 ;
  while (1)
    {
      char find[strlen(seek) + 1] ;
      const char* t ;
      int n ;

      s = strpbrk(s, seek) ;
      if ((s == NULL) || (strlen(s) < strlen(seek)))
        break ;

      strcpy(find, seek) ;
      t = s ;
      n = strlen(find) ;
      while (1)
        {
          char* f ;

          f = strchr(find, *t) ;
          if (f == NULL)
            break ;

          n -= 1 ;
          if (n == 0)
            {
              count += 1 ;
              break ;
            } ;

          *f = find[n] ;
          find[n] = '\0' ;

          t += 1 ;
        } ;

      s += 1 ;
    } ;

  printf("'%s' in '%s' %d times\n", seek, test, count) ;    

...最后的s += 1可以s += strlen(seek)超越比赛,如果这是必要的。