問題描述:
有n個長為m+1的字串,如果某個字串的最後m個字元與某個字串的前m個字元匹配,則兩個字串可以串連。問這n個字串最多可以連成一個多長的字串,如果出現迴圈,則返回錯誤。
分析:
把每個字串看成一個圖的頂點,兩個字串可以串連就形成一條有向邊。相當於判斷一個有向圖是否存在環以及求該有向圖的最長路徑。
可用圖的深度優先遍曆演算法來求解,圖用鄰接表表示。
1. 求解有向圖是否存在環及最長路徑
#define VERTEX_NUM7#define NOT_VISITED-1//該頂點未被訪問#define VISITED0//該頂點已經被訪問,但它的鄰接點未被訪問完成#define FINISHED1//結束訪問該頂點的鄰接表#define IS_CIRCLE-1int maxLen = -1;int getMaxLenInGraph(int adj[][VERTEX_NUM]); //返回-1表示該有向圖中存在環路int DFS_VISTI(int state[], int adj[][VERTEX_NUM], int i, int *len); //深度優先遍曆int getMaxLenInGraph(int adj[][VERTEX_NUM]){int state[VERTEX_NUM];for (int i = 0; i < VERTEX_NUM; i++)state[i] = NOT_VISITED;int tempLen;for (int i = 0; i < VERTEX_NUM; i++){tempLen = 0;if (state[i] == NOT_VISITED){if (DFS_VISTI(state, adj, i, &tempLen) == IS_CIRCLE)return IS_CIRCLE;}}return maxLen;}//state[i]儲存頂點i的狀態,adj[i][]數組中儲存所有與頂點i相鄰的頂點int DFS_VISTI(int state[], int adj[][VERTEX_NUM], int i, int *len){state[i] = VISITED;for (int j = 1; adj[i][j] != -1; j++){if (state[adj[i][j]] == NOT_VISITED){(*len)++;if (DFS_VISTI(state, adj, adj[i][j], len) == IS_CIRCLE)return IS_CIRCLE;}else if (state[adj[i][j]] == VISITED)//這樣表示環的存在,經得起考驗嗎?{*len = IS_CIRCLE;return IS_CIRCLE;}}state[i] = FINISHED;if (*len > maxLen)maxLen = *len;*len = 0;return 0;}
測試代碼:
int main(){//圖的鄰接表資料,-1表示結束int Adj[VERTEX_NUM][VERTEX_NUM] = {{0, 1, 3, -1},{1, 2, 3, 4, -1},{2, 3, 4, 5, -1},{3, 4, -1},{4, 5, -1},{5, 6, -1},{6, -1}//改為6, 0, -1 則表示存在環};int len = getMaxLenInGraph(Adj);printf("the length of graphic is : %d\n", len);system("pause");return 0;}
2.求解能串連成的最長字串( 首先建圖,然後利用上面提供的函數即可求解 )
代碼實現如下:
#include <iostream>#include <string>using namespace std;#define VERTEX_NUM8#define NOT_VISITED-1//該頂點未被訪問#define VISITED0//該頂點已經被訪問,但它的鄰接點未被訪問完成#define FINISHED1//結束訪問該頂點的鄰接表#define IS_CIRCLE-1int maxLen = -1;int getMaxLenInGraph(int adj[][VERTEX_NUM]); //返回-1表示該有向圖中存在環路int DFS_VISTI(int state[], int adj[][VERTEX_NUM], int i, int *len); //深度優先遍曆void build_graph(string str[], int graph[][VERTEX_NUM]);int main(){string str[] = {"abc", "bcf", "cfg", "fga", "gam", "bcg", "cga", "gai",};//其鄰接表,若改變4節點為"gab",則出現迴圈//0-1-5//1-2//2-3//3-4-7//4//5-6//6-4-7//7int Graph[VERTEX_NUM][VERTEX_NUM];//構造圖的鄰接表build_graph(str, Graph);int len = getMaxLenInGraph(Graph);printf("該有向圖最長路徑為(-1表示存在環): %d\n", len);if (len != -1)printf("可以串連成的最長字串為:%d\n", str[0].length()+len);system("pause");return 0;}void build_graph(string str[], int gra[][VERTEX_NUM]){for (int i = 0; i < VERTEX_NUM; i++)for (int j = 0; j < VERTEX_NUM; j++){if (j == 0)gra[i][j] = i;elsegra[i][j] = -1;}int index;for (int i = 0 ; i < VERTEX_NUM; i++){index = 1;string suffix = str[i].substr(1);for (int j = 0; j < VERTEX_NUM; j++){if (str[j].find(suffix) == 0)gra[i][index++] = j;}}}
出現問題在所難免,如有發現錯誤的朋友,請指正!
註:運行時會提示棧溢出的問題,修改property->configuration properties -> linker -> system中的stack reserve size和 stack commit size即可~