網上遇到乙個很有意思的題目
2.分析解
a.很明顯是一顆解空間樹.先來分析一下這個問題的結構
比如
待測字串: s1="1234";待測字串s1長度為4,有4*3*2*1=24種排列組合目標字串: s2="3124";
先思考最多需要幾次修改,能 任一排列-->任一排列
①窮舉法:
1次:算上本身只有4個分支
2次:有1+3+9=13個分支
3次:有1+3+9+27=40個分支,>24
最多要3次(size-1次)
②分析法
修改後字串 0
123修改後字串 第3位 來自於待測字串 最晚移動 的字元 or 無移動
修改後字串 第2位 來自於待測字串 第二晚移動 的字元 or 無移動
修改後字串 第1位 來自於待測字串 第三晚移動 的字元 or 無移動
修改後字串 第0位 來自於待測字串未移動的字元
也就是說:4字元的串,從任一排列-->任一排列,一定會經過[0,3]次移動
推廣:n個字元的字串,需要[0,n-1]次移動,可到達全部排列方式
解空間樹是n-1叉樹,深度為n-1(根節點深度=0)
b.那麼應該用深度遍歷(回溯法)還是廣度遍歷(分支限界法)呢?
一開始用的是回溯法,發現不是很合適.實際解是乙個最小值.
如果實際解很小.深度遍歷卻已經達到很深的葉結點.而且需要不斷地遞迴、恢復父結點狀態.十分麻煩
應該按照貪心的原則,從淺層-->深層
1.全域性變數
using namespace std;
#include#include#include#include//定義全域性變數
class str
; str(string _s, int _count) :s(_s), count(_count) {};
string s; //需要檢測的字串
int count = 0; //當前狀態的修改次數
};
2.部件函式,用來執行" 將選中字元挪到末尾 "操作
//將字串當前位置字元->end
string move2end(int index, str str)
3.分支限界法求解問題,按照要求返回值
//按回溯法尋找最優解,count初值=0,記錄操作次數
int movestrtrack(string s1, string s2)
//建立佇列
queueq;
str livenode,newnode;
newnode = str(s1, 0); //根節點修改次數=0
q.push(newnode); //先進根節點,開動迴圈
int sizeofstr = s1.size();
while (!q.empty())
continue; //跳過本次迴圈
} //終止條件
if ((!q.empty())&&(q.front().count>=sizeofstr)) //佇列不空&&到達葉結點的子節點.此時不存在s1->s2的可能性
//開始搜尋子節點
for (int i = 0; i < sizeofstr - 1; i++) //只遍歷第[0,size-2]個字元
else
}} return 0; //執行到此處,說明佇列空了也沒有找到匹配,返回0
}
4.呼叫函式
//呼叫
void movestr()
else
}//呼叫輸出
cout << s1 << endl << s2 << endl;
cout << "s1的最少移動次數: " << movestrtrack(s1, s2);;
}
模板 字串演算法 字串最小表示法
2014年10月,剛進hdu參加新生賽的時候,就遇到了字串最小表示法的裸題,然而那時什麼都不會的我只得寫暴力,自然tle了。之後在 湖南師範大學第六屆大學生計算機程式設計競賽2b 上,又做到了同樣的裸題。字串演算法 字串最小表示法模板 這是乙個可以用o n 時間解決 字串呈環狀,每一位置都可以作為首...
字串最小表示法 O(n 演算法
網上看了這篇文章後還是感覺有些地方講的沒有詳細的證明所以新增了一點 紅色字是博主寫的 求字串的迴圈最小表示 上面說的兩個字串同構的,並沒有直接先求出min s 而是通過指標移動,當某次匹配串長時,那個位置就是min s 而這裡的問題就是 不是給定兩個串,而是給出乙個串,求它的min s eg min...
sunday演算法研究 超越kmp的字串匹配
第一次聽到sunday演算法,是大餅餅說的。在他 並茂的解釋中,我發現這個演算法果然是乙個又容易理解,效率又強過kmp和bm的演算法。於是試著寫了乙個,果真是好東東,分享一下。轉一些概念先 sunday演算法是daniel m.sunday於1990年提出的一種比bm演算法搜尋速度更快的演算法。其核...