【编程题目】有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配...
37.(字符串)
有 n 个长为 m+1 的字符串,
如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配,则两个字符串可以联接,
问这 n 个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。
分析:如果出现循环,则返回错误 这句不懂 我采用了绝对不会产生环的方法来做。
具体做法是先给每个字符串建一个vector 存入每个字符串后面可以匹配的字符串序号
然后遍历所有的搭配情况,找到最长的。
我的遍历代码很丑... 可谓又臭又长..... 深深的自我鄙视。
/* 37.(字符串) 有 n 个长为 m+1 的字符串, 如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配,则两个字符串可以联接, 问这 n 个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。 start time = 18:27 end time = */ #include <iostream> #include <vector> #include <string> using namespace std; //判断两个字符串能否拼接 0表示不能 2表示s1在前 1表示s2在前 int contact(string s1, string s2, int m) { if(s1.substr(0, m) == s2.substr(s2.length() - m, m)) return 1; else if(s2.substr(0, m) == s1.substr(s1.length() - m, m)) return 2; else return 0; } void getMax0(vector<int> now, vector<vector<int>> can_compare, vector<int> &max) { bool isfind = false; int last = now.back(); vector<int>::iterator it; for(it = can_compare.at(last).begin(); it < can_compare.at(last).end(); it++) { bool isHave = false; vector<int>::iterator it2; for(it2 = now.begin(); it2 < now.end(); it2++) { if((*it) == (*it2)) { isHave = true; break; } } if(isHave == false) { isfind = true; now.push_back(*it); getMax0(now, can_compare, max); now.pop_back(); } } if(isfind == false) { if(now.size() > max.size()) { max = now; } } } vector<int> getMax(vector<vector<int>> can_compare) { vector<int> contact; vector<int> max; vector<int> now; vector<vector<int>>::iterator it; for(int i = 0; i < can_compare.size(); i++) { now.push_back(i); getMax0(now, can_compare, max); now.clear(); } return max; } //返回可能的最大长度 string maxLength(vector<string> S, int m) { //找到每个字符串在前时有哪些其他字符串可以与其匹配 vector<vector<int>> can_compare; vector<string>::iterator it; for(it = S.begin(); it < S.end(); it++) { vector<int> can_member; vector<string>::iterator it2; int n = 0; for(it2 = S.begin(); it2 < S.end(); it2++) { if(it != it2) { if(contact(*it, *it2, m) == 2) { can_member.push_back(n); } } n++; } can_compare.push_back(can_member); } vector<int> maxStringMember = getMax(can_compare); vector<int>::iterator it3; string ans = S.at(maxStringMember.at(0)); for(it3 = maxStringMember.begin() + 1; it3 < maxStringMember.end(); it3++) { string after = S.at(*it3); ans.append(after.substr(after.length() - 1, 1)); } cout << "the max length is "<< ans.length() << endl; cout << "the string is " << ans << endl; return ans; } int main() { vector<string> S; string s1 = "abd"; S.push_back(s1); string s2 = "bcd"; S.push_back(s2); string s3 = "cde"; S.push_back(s3); string s4 = "def"; S.push_back(s4); string ans = maxLength(S, 2); return 0; }
在网上看答案,发现这是一道图的题。可以通过floyd求最大路径来解决。
从网上找了一份代码,验证了可以使用。
代码中D[v][w] 是顶点v到顶点w的最大路径
p[v][w][u]是顶点v到顶点w最大路径上第u个顶点的序号。
INFINITY 顶点间无边时的值,是个负数
算法原理是,如果发现v 、w顶点中插入顶点u距离变大,则更新最大路径和最大距离。
代码如下:http://blog.csdn.net/cxllyg/article/details/7606599
#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; system("pause"); }