兩個經典回文字串問題中的巧妙演算法

2021-09-23 02:01:38 字數 2471 閱讀 1306

問題一:(最長回文子串)給定乙個字串 s,找到 s 中最長的回文子串。

第一眼的想法是暴力法,由於其時間複雜度高達o(n^3),當s過長時效率會特別低。

方法一:中心擴充套件演算法

其思想就是遍歷一遍字串,其中在每乙個點都進行以其為中心而均勻展開(分奇偶),然後找到每個點能夠展開到的最大值,最後也就不難得到最長回文串了。

具體**如下:

public string longestpalindrome1(string s) 

}return s.substring(start, end + 1);

}private int expandaroundcenter(string s, int left, int right)

return r - l - 1;

}

方法二:manacher 演算法

其思想就是將原字串用同一的符號擴充套件兩倍+1,這樣可以巧妙的迴避了奇偶回文串的問題。然後再定義乙個類似計數排序的乙個計數陣列,用它在擴充套件後的字串上進行型別中心擴充套件的操作。最終的manacher 演算法還有乙個對計數陣列的乙個演算法優化。

具體**如下:

public string longestpalindrome2(string s) 

ah[2 * s.length()] = '#';

int arr = manacher1(ah);

return s.substring((arr[1] - arr[0]) / 2, (arr[1] + arr[0]) / 2);

}private int manacher1(char t)

for (int i = 0; i < len.length; i++)

ans = math.max(ans, len[i]);

}arr[0] = ans - 1;

int i = 0;

while (len[i] != ans)

arr[1] = i;

return arr;

}private int manacher2(char t) else

while ((i - len[i] >= 0) && (i + len[i] < len.length) && t[i - len[i]] == t[i + len[i]])

if (len[i] + i > mx)

ans = math.max(ans, len[i]);

}arr[0] = ans - 1;

int i = 0;

while (len[i] != ans)

arr[1] = i;

return arr;

}

問題二:(最短回文串)給定乙個字串 s,你可以通過在字串前面新增字元將其轉換為回文串。找到並返回可以用這種方式轉換的最短回文串。

思路:由於只能在字串的前面新增字元,所以不由的想出要先找到原字串的最長字首回文串,下面給出兩種方法。

方法一:直接尋找

這裡需要倒序遍歷字串,定義一頭一尾兩個指標,再用乙個while的內迴圈來取得其最長的字首回文串。

具體**如下:

public string shortestpalindrome1(string s) 

int x = getfronts(s);

return new stringbuilder(s.substring(x + 1)).reverse().tostring() + s;

}//獲得原字串的最長字首回文字串長度

private int getfronts(string s)

else

}if (a >= b)

a = 0;}}

return 0;

}

方法二:kmp演算法的next陣列

這個next陣列也很類似計數排序的那個計數陣列,只不過這個陣列記錄的是當前位置的最大字首數,有了這個陣列,最長字首回文串也就手到擒來了。

具體**如下:

public string shortestpalindrome2(string s) 

string temp = s + "#" + new stringbuilder(s).reverse().tostring() + "#";

//中間那個#是為了把兩段字串分隔開,避免產生干擾

int next = getnext1(temp);

int index = next[temp.length()-1]; //取得最長字首回文字串的下標

return new stringbuilder(s.substring(index)).reverse().tostring() + s;

}private int getnext1(string p)

}return next;

}

特別是後面的manacher 演算法和kmp演算法都很巧妙也很有回味價值。

動態規劃的兩個經典問題

weight 原始物品陣列,values 為其所對應的價值,n 表示物品的個數,w 表示揹包所能承受的最大重量 public void knapsack3 int weight,int values,int n,int w states 0 0 0 if weight 0 w for int i 1...

字串處理的兩個問題

處理字元是c語言中的常見操作,有兩個問題需要討論 一是判斷字元處理結束的標誌是空字元還是換行符,二是迴圈處理字元時,迴圈次數是字元陣列的容量大小還是實際輸入字元的個數。舉例 鍵盤輸入一行字元,統計大寫字元的個數。本例可用兩種方法程式設計,第一種方法的 如下 include int main 下面是第...

動態規劃的兩個經典問題 01揹包

學動態規劃要從經典問題開始 by lrj 答應了小q要寫這個的.哎.先說那個什麼01揹包.為什麼叫揹包呢?因為這些問題的原型是說有很多東西,每個東西都有體積,也有價值,你要去春遊,要選一些東西放到揹包裡.問題是要怎麼選才能在總體積不超過揹包的體積的前提下,讓總價值最大.為什麼是0 1呢?因為每種東西...