题目:http://codevs.cn/problem/1018/
思路:合并字符串a,b。从字符串a的末尾字符a[ai]与字符串b的首字符b[bi]进行匹配,如果不相等,则ai - 1;如果相等,则匹配ai+x,与bi+x的字符是否相等,如果到达字符串a的结尾且ai不等于0,即b不包含a,则表示合并成功,记录合并位置,否则ai - 1。
题解:
/* 1018 单词接龙 */
#include <stdio.h>
#include <stdlib.h>
#define DEBUG
#define MAXN 20 /* 最大单词数 */
#define MAXL 50 /* 最长的单词长度 */
int n; /* 单词数 */
char words[MAXN][MAXL]; /* 所有单词 */
char st_ch; /* 开始单词 */
int use[MAXN]; /* 使用表 */
int maxl; /* 最长接龙数 */
/* 获取字符串长度 */
int get_len(char *str){
int l = 0;
while('\0' != str[l]){
l++;
}
return l;
}
/* 连接两个单词,可连接返回连接后的字符串,否则NULL */
char* conn_str(char *stra, char *strb){
int ai, bi;
int x;
char *strc = NULL;
int done;
int la, lb, lc;
/* 计算字符串长度 */
la = get_len(stra);
lb = get_len(strb);
/* 遍历字符串a,b, 查询重复字符串 */
ai = bi = 0;
done = 0;
for(ai = la - 1; ai >= 0; ai--){
/* 如果两字符串相等,则继续判断下一个字符 */
if(stra[ai] == strb[bi]){
/* 判断接下来的字符,直到不等,或者字符串a,b结束 */
for(x = 1; (ai + x) < la && (bi + x) < lb; x++){
/* 字符串b已结束或者字符串a,b不再相等 */
if(stra[ai + x] != strb[bi + x]){
break;
}
}
/* 字符串a结束且字符串b不包含字符串a,匹配成功 */
if((ai + x) == la && 0 != ai){
done = 1;
break;
}
}
}
/* 匹配成功,合并字符串a和b */
if(1 == done){
lc = la + lb - x;
strc = (char*) malloc(lc + 1);
for(x = 0; x < ai; x++){
strc[x] = stra[x];
}
for(bi = 0; bi < lb; bi++){
strc[x + bi] = strb[bi];
}
strc[lc] = '\0';
/* 测试 - 打印合并后的字符串 */
// printf("%s + %s = %s [%d]\n", stra, strb, strc, get_len(strc));
}
return strc;
}
/* 深度搜索所有合并可能 */
void dfs_conn_strs(char *str){
int i;
char *tmp;
int l;
/* 遍历所有字符串,查找可能的连接字符串 */
for(i = 0; i < n; i++){
/* 当前字符串未被使用, 且可以连接 */
if(0 != use[i] && NULL != (tmp = conn_str(str, words[i]))){
use[i] = use[i] - 1;
dfs_conn_strs(tmp);
use[i] = use[i] + 1;
free(tmp);
}
}
/* 搜索完毕,计算长度 */
l = get_len(str);
if(l > maxl){
maxl = l;
}
/* 测试 - 打印合并的字符串 */
// printf("%s\n", str);
}
/* 主函数入口 */
int main(int argc, char *argv[]) {
int i; /* 索引值 */
#ifdef DEBUG
FILE *fp;
if(NULL == (fp = fopen("data.txt", "r"))){
return 1;
}
#endif
/* 获取单词数 */
#ifdef DEBUG
fscanf(fp, "%d", &n);
#else
scanf("%d", &n);
#endif
/* 获取所有单词 */
for(i = 0; i < n; i++){
#ifdef DEBUG
fscanf(fp, "%s", words[i]);
#else
scanf("%s", words[i]);
#endif
}
/* 获取起始单词 */
#ifdef DEBUG
fscanf(fp, "\n%c", &st_ch);
#else
scanf("\n%c", &st_ch);
#endif
/* 初始化单词使用表 */
for(i = 0; i < n; i++){
use[i] = 2;
}
/* 测试 - 打印所有单词 */
/*
for(i = 0; i < n; i++){
printf("%s\n", words[i]);
}
printf("%c\n", st_ch);
*/
/* 搜索最长接龙 */
maxl = 0;
for(i = 0; i < n; i++){
if(st_ch == words[i][0]){
use[i] = use[i] - 1;
dfs_conn_strs(words[i]);
use[i] = use[i] + 1;
}
}
/* 输出结果值 */
printf("%d", maxl);
#ifdef DEBUG
fclose(fp);
#endif
return 0;
}