<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 最長公共子序列和最長公共子串區別 ????? 最長公共子串(Longest Common Substring)與最長公共子序列(Longest Common Subsequence)的區別: 子串要求在原字符串中是連續的,而子序列則只需保持相對順序一致,并不要求連續。例如X = {a, Q, 1, 1}; Y = {a, 1, 1, d, f}那么,{a, 1, 1}是X和Y的最長公共子序列,但不是它們的最長公共字串。 # 一、最長公共子序列 具體的算法思想參考以下文章: [http://blog.csdn.net/lisonglisonglisong/article/details/41548557](http://blog.csdn.net/lisonglisonglisong/article/details/41548557) [http://blog.csdn.net/zhongkeli/article/details/8847694](http://blog.csdn.net/zhongkeli/article/details/8847694) [![](https://box.kancloud.cn/2016-06-07_575683a56b6e2.jpg) ](http://blog.csdn.net/zhongkeli/article/details/8847694) ### 只求最長子序列長度 ![](https://box.kancloud.cn/2016-06-07_575683a585d0b.jpg) 如果僅僅需要知道最長子序列的長度值,代碼如下: ~~~ #include <vector> #include <string> #include <iostream> #include <string.h> #include <sstream> using namespace std; //最長公共子串(LCS) //二維數組veca記錄的是兩個字符串Xi和Yj的LCS長度 int LCS_length(const string &str1, const string &str2, vector<vector<int> > &veca) { int i, j; int biggest = 0; if (str1 == "" || str2 == "") return 0; for (i = 0; i <= str1.length(); i++) { veca[i][0] = 0; } for (j = 0; j <= str2.length(); j++) { veca[0][j] = 0; } for (i = 1; i <= str1.length(); i++) { for (j = 1; j <= str2.length(); j++) { if (str1[i - 1] == str2[j - 1]) { veca[i][j] = veca[i - 1][j - 1] + 1; } else { if (veca[i - 1][j] >= veca[i][j - 1]) veca[i][j] = veca[i - 1][j]; else veca[i][j] = veca[i][j-1]; } } } return veca[str1.length()][str2.length()]; } int main() { string input; getline(cin, input); stringstream ss(input); string str1, str2; ss >> str1; ss >> str2; //將veca初始化為一個二維數組,其行列值分別為str1和str2的長度加1 //二維數組veca記錄的是兩個字符串Xi和Yj的LCS長度 vector<vector<int> > veca(str1.length() + 1, vector<int>(str2.length() + 1)); cout << LCS_length(str1, str2, veca) << endl; return 0; } ~~~ 結果: ![](https://box.kancloud.cn/2016-06-07_575683a597c01.jpg) 動態規劃解決LCS問題的時間復雜度為O(mn),這比簡單的遞歸實現要快多了。空間復雜度是O(mn),因為使用了一個動態規劃表。 ### 要輸出一個LCS的內容 和上面的程序比,只需要多一個二維數組記錄在遍歷中所選擇的子問題的最優解即可。如下程序: ~~~ //輸出最長公共子串(LCS) //二維數組veca記錄的是兩個字符串Xi和Yj的LCS長度 int LCS_length(const string &str1, const string &str2, vector<vector<int> > &veca, vector<vector<int> > &vecb) { int i, j; int biggest = 0; if (str1 == "" || str2 == "") return 0; for (i = 0; i <= str1.length(); i++) { veca[i][0] = 0; } for (j = 0; j <= str2.length(); j++) { veca[0][j] = 0; } for (i = 1; i <= str1.length(); i++) { for (j = 1; j <= str2.length(); j++) { //如果Xi-1 == Yj-1,那么最長子序列為veca[i - 1][j - 1] + 1 //此時將vecb[i][j] = 1表明str1[i-1]是子問題LCS的一個元素 if (str1[i - 1] == str2[j - 1]) { veca[i][j] = veca[i - 1][j - 1] + 1; vecb[i][j] = 1; } else { if (veca[i - 1][j] >= veca[i][j - 1]) { veca[i][j] = veca[i - 1][j]; vecb[i][j] = 2; } else { veca[i][j] = veca[i][j-1]; vecb[i][j] = 3; } } } } return veca[str1.length()][str2.length()]; } //該函數用于輸出一個LCS的序列 //這里輸出的順序是先向上尋找,再向左尋找 void PrintOneLCS(vector<vector<int> > &vecb, string &str1, int i, int j) { if (i == 0 || j == 0) return; if (vecb[i][j] == 1) { PrintOneLCS(vecb, str1, i - 1, j - 1); cout << str1[i - 1] << " "; } else if (vecb[i][j] == 2) PrintOneLCS(vecb, str1, i -1, j); else PrintOneLCS(vecb, str1, i, j - 1); } int main() { string input; getline(cin, input); stringstream ss(input); string str1, str2; ss >> str1; ss >> str2; //將veca初始化為一個二維數組,其行列值分別為str1和str2的長度加1 //二維數組veca記錄的是兩個字符串Xi和Yj的LCS長度 //二維數組vecb[i][j]記錄veca[i][j]時所選擇的子問題的最優解 vector<vector<int> > veca(str1.length() + 1, vector<int>(str2.length() + 1)); vector<vector<int> > vecb(str1.length() + 1, vector<int>(str2.length() + 1)); cout << LCS_length(str1, str2, veca, vecb) << endl; PrintOneLCS(vecb, str1, str1.length(), str2.length()); return 0; } ~~~ ![](https://box.kancloud.cn/2016-06-07_575683c0b43b3.jpg) 求一個LCS內容也可以不借助輔助二維數組vecb而是用下面小節的方法, ~~~ //該函數用于輸出一個LCS的序列,使用下一小節的方法 //這里輸出的順序是先向左尋找,再向上尋找 void PrintOneLCS(string &str1, string &str2, int i, int j, vector<vector<int> > &veca) { string lcs_str; while (i > 0 && j > 0) { if (str1[i - 1] == str2[j - 1]) { lcs_str = str1[i - 1] + lcs_str; --i; --j; } else { //如果左邊存在LCS就從左邊找否則再從右邊找 if (veca[i - 1][j] >= veca[i][j - 1]) --i; else --j; } } cout << lcs_str << endl; } ~~~ 如下代碼: ### 要輸出所有LCS的內容 兩個字符串對應的最長公共子序列不一定唯一,這個程序輸出所有的LCS內容。 基本思想是: ![](https://box.kancloud.cn/2016-06-07_575683c0c4e99.jpg) 具體參考文章:[http://blog.csdn.net/lisonglisonglisong/article/details/41596309](http://blog.csdn.net/lisonglisonglisong/article/details/41596309) 代碼: ~~~ #include <vector> #include <iomanip> #include <set> #include <string> #include <map> #include <iostream> #include <string.h> #include <sstream> using namespace std; set<string> all_lcs; //注意這里要用set去除重復的LCS //最長公共子串(LCS) //二維數組veca[i][j]記錄的是兩個字符串Xi和Yj的LCS長度 int LCS_length(const string &str1, const string &str2, vector<vector<int> > &veca) { int i, j; int biggest = 0; if (str1 == "" || str2 == "") return 0; for (i = 0; i <= str1.length(); i++) { veca[i][0] = 0; } for (j = 0; j <= str2.length(); j++) { veca[0][j] = 0; } for (i = 1; i <= str1.length(); i++) { for (j = 1; j <= str2.length(); j++) { if (str1[i - 1] == str2[j - 1]) { veca[i][j] = veca[i - 1][j - 1] + 1; } else { if (veca[i - 1][j] >= veca[i][j - 1]) veca[i][j] = veca[i - 1][j]; else veca[i][j] = veca[i][j-1]; } } } return veca[str1.length()][str2.length()]; } //該函數找出所有的LCS的序列,并將其存在vector中 void PrintAllLCS(string &str1, string &str2, int i, int j, vector<vector<int> > &veca, string lcs_str) { //注意這里形參lcs_str不可以為引用,這里需要每次調用lcs_str都重新生成一個對象 while (i > 0 && j > 0) { if (str1[i - 1] == str2[j - 1]) { lcs_str = str1[i - 1] + lcs_str; //逆向存放 --i; --j; } else { if (veca[i - 1][j] > veca[i][j - 1]) //向左走 --i; else if (veca[i - 1][j] < veca[i][j - 1]) //向上走 --j; else { //此時向上向右均為LCS的元素 PrintAllLCS(str1, str2, i - 1, j, veca, lcs_str); PrintAllLCS(str1, str2, i, j - 1, veca, lcs_str); return; } } } cout << " " << lcs_str << endl; all_lcs.insert(lcs_str); } int main() { string input; getline(cin, input); stringstream ss(input); string str1, str2; ss >> str1; ss >> str2; //將veca初始化為一個二維數組,其行列值分別為str1和str2的長度加1 //二維數組veca記錄的是兩個字符串Xi和Yj的LCS長度 vector<vector<int> > veca(str1.length() + 1, vector<int>(str2.length() + 1)); cout << LCS_length(str1, str2, veca) << endl; string lcs_str; PrintAllLCS(str1, str2, str1.length(), str2.length(), veca, lcs_str); set<string>::iterator iter = all_lcs.begin(); while (iter != all_lcs.end()) { cout << *iter++ << endl; } return 0; } ~~~ ![](https://box.kancloud.cn/2016-06-07_575683c0da977.jpg) 如圖所示的兩個字符串共有三個LCS。 # 二、最長公共子串 **描述:** 計算兩個字符串的最大公共子串(Longest Common Substring)的長度,字符不區分大小寫。 **輸入:** 輸入兩個字符串 **輸出:** 輸出一個整數 **樣例輸入:** ~~~ asdfas werasdfaswer ~~~ **樣例輸出:** ~~~ 6 ~~~ 這里的**最大公共字串要求的字串是連續**的。 求字串的方法和求子序列方法類似: 當str1[i] == str2[j]時,子序列長度veca[i][j] = veca[i - 1][j - 1] + 1;只是當str1[i] != str2[j]時,veca[i][j]長度要為0,而不是max{veca[i - 1][j], veca[i][j - 1]}。 ~~~ #include <vector> #include <string> #include <iostream> #include <string.h> #include <sstream> using namespace std; int LCS_length(const string &str1, const string &str2, vector<vector<int> > &veca) { int i, j; int biggest = 0; if (str1 == "" || str2 == "") return 0; for (i = 0; i <= str1.length(); i++) { veca[i].resize(str2.length() + 1, 0); } for (j = 0; j <= str2.length(); j++) { veca[0][j] = 0; } for (i = 1; i <= str1.length(); i++) { for (j = 1; j <= str2.length(); j++) { if (str1[i - 1] == str2[j - 1]) { veca[i][j] = veca[i - 1][j - 1] + 1; if (veca[i][j] > biggest) biggest = veca[i][j]; } else //可以看出,求最長子串和求最長子序列差別僅僅在這里 veca[i][j] = 0; } } return biggest; } int main() { string input; getline(cin, input); stringstream ss(input); string str1; ss >> str1; string str2; ss >> str2; vector<vector<int> > veca(str1.length() + 1); cout << LCS_length(str1, str2, veca) << endl; return 0; } ~~~ 同樣適用求最長子序列的測試數據,得到它們的公共最長子串長度為2,而它們的公共最長子序列長度為4. ![](https://box.kancloud.cn/2016-06-07_575683c0ef705.jpg) # 三、動態規劃的其它題目 1、硬幣面值組合問題 [http://www.cnblogs.com/python27/archive/2013/09/05/3303721.html](http://www.cnblogs.com/python27/archive/2013/09/05/3303721.html) 2、[最長遞增子序列](http://blog.csdn.net/u013074465/article/details/45442067) ? ? ? ? ?除了動態規劃,該題還有其他解法。 3、數組最大子數組和的最大值 [http://www.ahathinking.com/archives/120.html](http://www.ahathinking.com/archives/120.html) 3、[動態規劃之鋼條分割](http://blog.csdn.net/u013074465/article/details/44920979) 4、計算兩個字符串的相似度(編程之美) ? ? ?該文章原理說得比較清楚:[點擊打開鏈接](http://www.cnblogs.com/tianchi/archive/2013/02/25/2886964.html) ? ? ?這里是代碼:[點擊打開鏈接](http://blog.csdn.net/zzran/article/details/8274735) 5、求每一對頂點之間的最短路徑:Floyd-Warshall算法
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看