假设我有一个字符串“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)
答案 0 :(得分:1)
首先为所有"ron"
排列设置Aho-Corasick状态机(这是很好的练习)然后将此计算机应用到第二个字符串。这是非常有效的解决方案,简短的第一个字符串。
编辑:我已经意识到Aho-Corasick状态机需要N!
内部状态,无论如何都会将其炸毁。必须构造一些具有压缩状态的其他类型的状态机。到目前为止,我正在思考找到的子字符串的链表,其中哈希表或线性表指向每个部分。
Edit2 :存在O(N+M)
时间和O(A)
空间复杂度的解决方案,其中N
和M
是输入字符串和{{的大小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)
超越比赛,如果这是必要的。