有难度的算法题,一齐思考吧!

szws 2005-04-08 09:21:27
加精
给定一组字符串,要求求出一个最短的字符串使得它包含所有给出的字符串。
比如"a","bc","ca".输出应该是"bca".
...全文
322 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
gumbour 2005-04-13
  • 打赏
  • 举报
回复
其实可以转化为图论的最短路径问题解决
Step1 去掉所有被其他字符串包含的字符串
例如 abc bc则可以当bc不存在
Step2 找出 和其他字符串首位不衔接的字符串
例如 存在abc 但不存在以a结尾和或以c开头的字符串
Step3 前两种字符串并不需要我们计算,关键是其余的字符串
我们建立一个邻接矩阵d[N][N]来表示2个字符串之间的距离,
具体的含义:d[i][j]表示第i个字符串后面连接第j个字符串所增加的长度
d[i][i]表示strlen(i)
这是一个非对称矩阵
例如 str[1]= "abcd"
str[2]= "cdefa"
则 d[1][2] = strlen("abcdefa") - strlen("abcd") = 3
d[2][1] = strlen("cdefabcd")- strlen("cdefa")= 3
再加一个额外的点 --第0个点
第0个点到任一点的距离就是这个点所代表的字符串长度
这样问题就转化城市连接问题 地点到i点的距离为d[i][i]
最后再加上Step2的字符串的所有长度就是结果了
城市连接问题:
某一地区有若干个主要城市,现准备修建高速公路把这些城市连接起来,使得从其中任何一个城市都可以经高速公路直接或间接到达另一个城市。假定已经知道了任意两个城市之间修建高速公路的成本,那么应如何决定在哪些城市间修建高速公路,使得总成本最小?
关于城市连接问题 在很多算法教材里是作为例题讲解的
cosio 2005-04-11
  • 打赏
  • 举报
回复
标准做法是玫举所有排列

就有这种方法完整找全所有的字符串

如:123 456 abc efg

所有的字符串?
galois_godel 2005-04-11
  • 打赏
  • 举报
回复
以前有2道acm题目就是这样的,标准做法是玫举所有排列
xiaohaiyan 2005-04-11
  • 打赏
  • 举报
回复

/*
大家看看这样的优化方法可行否:

StringSet = { "ae","bc", "bca","aef","eap","abc"};

1. 进行类Radix 排序的方式,结束之后,相互包含的字符串将被合并

进行LSD 基数排序,如果高位不存在则按次高位进行排序,
插入的时候进行strstr搜索,合并包含的字符
1)
a->bca
b->
c->(bc)->abc 插入的时候合并了bc
e->ae
f->aef
p->eap

Result :bca ,abc,ae,aef,eap
2)
a->eap
b->abc
c->bca
e->(ae)->aef 插入的时候合并了ae
f->
p->

Result : eap,abc,bca,aef
3)
a->abc->aef
b->bca
c->
e->eap
f->
p->

Result : abc, aef, bca,eap

上述算法时间复杂度为: O(d(n+ 26 ) )

( 如果在此基础上再进行全排列寻找也可以,上述方法应该能将算法复杂度降低一个层次)

现在的问题是能否对首尾重合的字符串合并提出一个比较好的算法

还请多多执教




*/


xdspower 2005-04-11
  • 打赏
  • 举报
回复
理论上 xiaohaiyan(xiaohaiyan)的方法在字符串比较少的情况下是可行的,但复杂度随字符串的增加增加太快了.所以楼主说这个是一个有难度的算法题确实如此啊.
xiaohaiyan 2005-04-11
  • 打赏
  • 举报
回复
上述程序得到的最优解:
b c a e f e p

e p b c a e f
xiaohaiyan 2005-04-11
  • 打赏
  • 举报
回复
按照 galois_godel思路写的程序:思路是这样的
1.找出最小字符集,如"ae", "bc", "bca", "aef", "ep",最小字符集是 "abcefp"
2.记录每个字符的出现次数
3.在最小字符集的基础上,按照每个字符出现次数扩大字符集
4.在字符集上进行全排列并strstr所有的字符串,首先找出来的应该是最优解

char *string [] = { "ae", "bc", "bca", "aef", "ep"};
int seq[26] = {0};
int minCount = 0x0fffff;


void print_array(char array[],int n)
{
for ( int i = 0;i < n; i++ )
printf("%c ",array[i] );
printf("\n");
}

int swap ( char * array , int i, int j )
{
char temp ;
temp = array[i];
array[i] = array[j] ;
array[j] = temp;
return 0;
}

int permute (char array[],int left, int n, char* string[] )
{
int i =0;
int t = 1, pos = 0;

if ( left < n -1)
{
permute(array, left + 1 ,n,string );/*Output every permute before swapping*/

for ( i = left +1 ; i < n; i++ )
{
swap (array, i, left);
permute(array, left + 1 ,n ,string);
swap(array, left, i);
}
}else{

while ( t && pos < 5) /*pos condition is important */
{
if ( strstr( array, string[pos] ) == NULL )
t = 0;
else
pos++;
}
if ( strlen ( array) > minCount )
t = 0;
else
minCount = strlen ( array );

if ( t )
print_array(array,n);
return 1;
}

return 0;
}

int seq_calculate ( int *array, char *string[] ,int num)
{
int i = 0 , j = 0;
char * p = NULL;

for ( i = 0; i < num; i++ )
{
p = string[ i ];
for ( j = 0; j < strlen (p ); j++ )
array[ p[j] -'a' ] ++;
}
return 0;
}

int minCharSet ( int * array, int size,char ** result )
{
int i = 0, count = 0, pos = 0;

for ( i = 0; i < size ; i++ )
if ( array[i] != 0 )
{
count++;
}

*result = (char * ) malloc ( count);

for ( i = 0; i < size ; i++ )
if ( array[i] != 0 )
{
(*result) [pos++] = i + 'a';
}

return count;

}


int minStringSet ( char * minSet, int setNum ,int seq[])
{
int i = 0, j = 0, count = 0, c = 0;
int pos = 0 , spos = 0;
char * expand_set = NULL;


for ( i = 0 ; i < 26 ; i ++ )
{
if ( seq[ i ] == 0 )
continue;
else
count = seq[ i] ;

expand_set = (char * ) malloc ( setNum + count );
for ( j = 1; j < count; j++ )
{
pos = spos = 0;
for ( c = 0 ; c< setNum + count ; c++ )
expand_set[c ] = 0;

for ( c = 0 ; c < setNum; c++ )
expand_set[pos++] = minSet [ spos++];

for ( c = 0 ; c< j ; c++ )
expand_set [pos++] = i +'a';

permute( expand_set, 0, setNum + j ,string);

}

free ( expand_set );

}

return 0;
}

void main ()
{
char * result = NULL;
int count = 0;

seq_calculate (seq, string, 5 );
count = minCharSet( seq,26, &result);

minStringSet(result, count, seq);
system("pause");

}

对比较多的字符集还没有进行测试,如xdspower() 所说,复杂度太高,不知大家还有没有其他的方法
xdspower 2005-04-11
  • 打赏
  • 举报
回复
枚举所有的?不大可能吧,空间和时间的复杂度都太高了.
xdspower 2005-04-10
  • 打赏
  • 举报
回复
123 45678 90ABCDE 234
比如这个串,最优串应该是1234567890ABCDE,但因为你只能确定一个添加模式,就可能构造的不是最优(小)串,比如构造成 4567890ABCDE1234所以在串很多的时候找出最优化的串是不可能的.
xdspower 2005-04-10
  • 打赏
  • 举报
回复
yinhongquan() 算法可以找到比较小的串,但不是最小串,而且对于很多情况,找出最小串可以说是不可能的,太复杂了,特别是串特别多的时候.不过构造一个策略来大大减少最终串的长度还是可能的.这就是yinhongquan() 的策略.
lrping 2005-04-10
  • 打赏
  • 举报
回复
1.找一个最长的串A;
2.在剩下的所有串中找到最长的串记为A1;
3.判断A1是否为A的子串,若是,转2,否则执行4;
4.在A1中找到最长子串A':A'为A1的开始子串且为A的结束子串,或者A'为A1的结束子串且为A的开始子串;
5.将A1中除了A'以外的另一部分子串加在A的结尾或者开始处。转2
直到所有字符串处理完毕;


这样找到的应该就是最短的。
szws 2005-04-09
  • 打赏
  • 举报
回复
一楼的大哥好像没理解题目的意思。
不是求包含所有字符的最小字符串,而是包含所有字符串的。

二楼的算法好像有点对,我试试吧!!
yinhongquan 2005-04-09
  • 打赏
  • 举报
回复
可不可以采用另外一种方法:

1。将quaster(quaster)代码中的二维数组str中长度最长的一个作为基本串,
2。将str中其他的字符串在基本串中进行查找,如果查找不到,则在基本串的头部查找从查找串尾部向前连续最大交集和从基本串尾部查找从查找串头部开始的最大交集,两者那个交集比较大,则在那个位置补充完整查找串。
3。重复第二步,直至所有子串。
quaster 2005-04-09
  • 打赏
  • 举报
回复
#include <stdio.h>
#include<conio.h>
int main()
{ char *str[3]={"a","bc","ca"},strshort[100]="",*p,c;
int i,j=0,result,k;
clrscr();
for(i=0;i<3;i++)/*三个字符串分别查找*/
{

p=str[i];
while((c=*p++)!='\0')/*查找每一个字符串*/
{
for(k=0,result=0;k<=j;k++)
{
if(c==strshort[k])
{
result=1;break;
}
}
if(result==0)
strshort[j++]=c;
}
}
printf("%s\n",strshort);
getch();
}

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧