【思考题】字串的连接最长路径查找

目标需求:

输入n个字符串,如果一个字符串末尾有k个字符与另一个字符串头k个字符相同,则这两个字符串可以连接,比如

abcdef     cdefgh这两个字符串可以连接成abcdefgh

从这n个字符串中,寻找可以连接成最长字串的方案。

//样例输入:
//ABCC ABCD BCCE BCDE CCEF BCCE CCEG CEGF                   
//样例输出:
//ABCCEGF

思路:

1.对所有字符串做编号1,2,3,4,5,.......;

2.对编号进行全排列;

3.对一次排列结果按排列编号进行连接,并记录最大连接长度方案。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int chongdie(char *s1, char *s2){
	int s1len, s2len;
	int k1, k2;
	int chongdie_cnt;

	s1len = strlen(s1);  s2len = strlen(s2);
	for(k1=0, k2=0, chongdie_cnt=0; k1<s1len; k1++){
		if(s1[k1]==s2[k2]){
			k2++;
			chongdie_cnt++;
		}
		else{
			if(chongdie_cnt>0)
				k1--;
			k2=0;
			chongdie_cnt = 0;
		}
	}

	return chongdie_cnt;
}

int *ans;
int max=0;
char **ss;

//全排列判断
void swap(int *a, int *b){
	int temp;

	temp = *a;
	*a = *b;
	*b = temp;
}

void quanpailie(int *data, int p, int n){
	int k;
	int i;
	int *data_backup;
	int ch_cnt=0;
	int temp;

	if(p>=n){
		for(k=1; k<n; k++){
			if((temp=chongdie(ss[data[k-1]], ss[data[k]]))==0){
				break;
			}
			else{
				if(k==1)
					ch_cnt += strlen(ss[data[k-1]])+strlen(ss[data[k]])-temp;
				else
					ch_cnt += strlen(ss[data[k]])-temp;
			}
		}
		if(ch_cnt>max){
			max = ch_cnt;
			memcpy(ans, data, sizeof(int)*n);
		}
		return;
	}

	data_backup = (int*)malloc(sizeof(int)*n);
	memcpy(data_backup, data, sizeof(int)*n);

	for(i=0; i+p<n; i++){
		swap(data_backup+p, data_backup+p+i);
		quanpailie(data_backup, p+1, n);
	}
	//free(data_backup);
}

//ABCC ABCD BCCE BCDE CCEF BCCE CCEG CEGF
int main(void){
	char **s;
	int s_num=20, s_size=0, sk;
	char temp[1000];
	char *stemp;
	int templen, ktemp, kptemp, k;
	int *used;
	int *data;

	s = (char**)malloc(sizeof(char*)*s_num);
	gets(temp);
	templen = strlen(temp);
	for(ktemp=0, kptemp=0; ktemp<=templen; ktemp++){
		if(temp[ktemp]==' '||temp[ktemp]=='\0'){
			if(ktemp<=kptemp)
				kptemp = ktemp+1;
			else{
				stemp = (char*)malloc(sizeof(char)*(ktemp-kptemp+1));
				memcpy(stemp, temp+kptemp, sizeof(char)*(ktemp-kptemp));
				stemp[ktemp-kptemp] = '\0';
				s[s_size++] = stemp;
				if(s_size==s_num){
					s_num += 20;
					*s = (char*)realloc(*s, sizeof(char*)*s_num);
				}
				kptemp = ktemp+1;
			}
		}
	}
	ans = (int*)malloc(sizeof(int)*s_size);
	ss = s;

	data = (int*)malloc(sizeof(int)*s_size);
	for(k=0; k<s_size; k++){
		*(data+k) = k;
	}
	memcpy(ans, data, sizeof(int)*s_size);
	//c++就用map,java就用hash,c呢?
	quanpailie(data, 0, s_size);

	for(k=1; k<s_size; k++){
		if((ktemp=chongdie(ss[ans[k-1]], ss[ans[k]]))==0){
			break;
		}
		else{
			if(k==1){
				printf("%s", ss[ans[k-1]]);
				printf("%s", ss[ans[k]]+ktemp);
			}
			else
				printf("%s", ss[ans[k]]+ktemp);
		}
	}

	system("pause");
	return 0;
}

为了提高速度,在进行下一层全排列前判断前面已排序的是否可以进行连接,从而决定是否进行下一层全排列;如果可以连接则进入下一级全排列,否则马上计算连接长度。
 结果演示:

posted @ 2014-08-13 01:06  浴火重生-xhyz  阅读(182)  评论(0编辑  收藏  举报