有n 个长为m+1 的字符串,求前后m个字符匹配所能形成的最长字符串链:利用弗洛伊德算法求最长路径

有n 个长为m+1 的字符串,如果某个字符串的最后m 个字符与某个字符串的前m 个字符匹配,则两个字符串可以联接,问这n 个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。

把字符串看成图中的一个顶点,两字符串匹配则两个顶点间有边,从而转化为图的问题。

利用弗洛伊德算法求图的最长路径。

#include <iostream>
#include <string>
using namespace std;

#define INFINITY -10000  
#define MAX_VERTEX_NUM 20 

typedef struct MGraph{
	string vexs[MAX_VERTEX_NUM];//顶点信息,这里就是要处理的字符串,每个字符串看做一个顶点
	int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵,符合条件的两个字符串之间有边
	int vexnum, arcnum;//顶点数就是字符串的个数
}MGraph;

void CreateDG(MGraph &G)//构造有向图
{
	int i, j;
	int m;
	cout<<"请输入要处理的字符串个数:";
	cin>>G.vexnum;

	cout<<"请输入这"<<G.vexnum<<"个字符串:";
	for(i=0; i<G.vexnum; i++)
		cin>>G.vexs[i];

	cout<<"请输入m:";
	cin>>m;

	for(i=0; i<G.vexnum; i++)
		for(j=0; j<G.vexnum; j++)
		{
			if(G.vexs[i].substr(G.vexs[i].size()-m,m)==G.vexs[j].substr(0,m))//根据前后m个字符是否匹配确定两字符串之间是否有边
				G.arcs[i][j]=1;
			else
				G.arcs[i][j]=INFINITY;
		}
}

//利用弗洛伊德算法求各顶点间的最长路径,p保存路径,D保存各顶点间的最长路径,如果出现循环,函数返回false,反之返回true
bool Largeset_FLOYD(MGraph G, int p[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM], int D[MAX_VERTEX_NUM][MAX_VERTEX_NUM])
{
	int v, w, u;
	int i, j;

	for(v=0; v<G.vexnum; v++)
		for(w=0; w<G.vexnum; w++)
		{
			D[v][w]=G.arcs[v][w];
			for(u=0; u<G.vexnum; u++)
				p[v][w][u]=-1;
			if(D[v][w]>INFINITY)
			{
				p[v][w][0]=v;
				p[v][w][1]=w;
			}
		}

	for(u=0; u<G.vexnum; u++)
		for(v=0; v<G.vexnum; v++)
			for(w=0; w<G.vexnum; w++)
			{
				if(D[v][u]>INFINITY && D[u][w]>INFINITY && D[v][u]+D[u][w]>D[v][w] )//改进的弗洛伊德算法,求最长路径
				{
					D[v][w]=D[v][u]+D[u][w];

					//更新p,以便打印路径
					for(i=0; i<G.vexnum; i++)
					{
						if(p[v][u][i]!=-1)
							p[v][w][i]=p[v][u][i];
						else
							break;
					}
					for(j=1; j<G.vexnum; j++)
					{
						if(p[u][w][j]!=-1)
							p[v][w][i++]=p[u][w][j];
						else
							break;
					}
					
				}
			}

	//判断是否有循环
	for(v=0; v<G.vexnum; v++)
		if(D[v][v]!=INFINITY)
				return false;
	
	return true;
}

void main()
{
	int i, j;
	int posx, posy;
	MGraph g;
	CreateDG(g);

	int p[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
	int D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
	bool flag=true;

	flag=Largeset_FLOYD(g, p, D);

/*	for(i=0; i<g.vexnum; i++)
	{
		for(j=0; j<g.vexnum; j++)
			cout<<D[i][j]<<" ";
		cout<<endl;
	}*/

	
	if(flag)
	{
		cout<<"最大长度为:";
		int max=-10000;
		for(i=0; i<g.vexnum; i++)
			for(j=0; j<g.vexnum; j++)
			{
				if(D[i][j]>max)
				{
					max=D[i][j];
					posx=i;
					posy=j;
				}
			}
    	cout<<max<<endl;
		cout<<"字符串链为:";
		for(i=0; i<g.vexnum; i++)//打印字符串链
		{
			if(p[posx][posy][i]!=-1)
				cout<<g.vexs[p[posx][posy][i]]<<" ";
		}
		cout<<endl;
	}
	else
		cout<<"错误:出现循环"<<endl;

}




有n 个长为m+1 的字符串,求前后m个字符匹配所能形成的最长字符串链:利用弗洛伊德算法求最长路径_第1张图片

你可能感兴趣的:(算法,struct,String)