问题:有n个长为m+1的字符串,如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以联接,问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。
分析:使用Floyd算法,设图G的顶点为V={1,2,...,n},对某个顶点k考虑顶点的一个子集,对任意一对顶点i,j属于V,考虑从i到j且中间顶点皆属于{1,2,...,k}的所有路径,假设p是其中一条最小权值路径,则k或者不是路径p上的一个顶点,或者是路径p上的一个顶点。若不是,则p的中间顶点是皆在{1,2,...,k-1}中;若k是路径p上的一个顶点,则满足
定义状态d(i,j,k),是从i到j经过顶点{1,2,...,k}的最短路径。
则可以有状态转移方程
d(i,j,k)=min{d(i,j,k-1),d(i,k,k-1)+d(k,j,k-1)}。
代码:
#include< iostream>
#include <string>
using namespace std;
using std::string;
void maxCatenat(string text[],const int n){
int **G = new int*[n];
for(int i=0;i<n;i++){
G[i] = new int[n]();
}
for(int i=0;i<n;i++){
string substr = text[i].substr(1);
for(int j=0;j<n;j++){
if(text[j].find(substr)==0)
G[i][j]=1;
}
}
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(G[i][k]!=0&&G[k][j]!=0){
int dist = G[i][k]+G[k][j];
if(dist>G[i][j])
G[i][j] = dist;
}
}
}
}
for(int i=0;i<n;i++){
if(G[i][i]>1){
cout<<"circle exist"<<endl;
return;
}
}
int maxdis = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
maxdis = std::max(maxdis,G[i][j]);
}
}
cout<<"max dis is:"<<maxdis<<endl;
}
void main(){
string text[] ={
"abcd",
"bcde",
"cdea",
"deab",
"eaba",
"abab",
"deac",
"cdei",
"bcdf",
"cdfi",
"dfic",
"cdfk",
"bcdg"
};
int n =sizeof(text)/sizeof(string);
maxCatenat(text,n);
}