回文子串劃分(基礎DP)- UVA 11584

2021-01-08 ACM算法日常

今天帶來一個簡單的線性結構上的DP,與上次的照明系統(UVA11400)是同一種類型題,便於大家類比、總結、理解,但難度上降低了。

We say a sequence of characters is a palindrome if it is the same written forwards and backwards. For example, 『racecar』 is a palindrome, but 『fastcar』 is not. A partition of a sequence of characters is a list of one or more disjoint non-empty groups of consecutive characters whose concatenation yields the initial sequence. For example, (『race』, 『car』) is a partition of 『racecar』 into two groups. Given a sequence of characters, we can always create a partition of these characters such that each group in the partition is a palindrome!

正序倒序寫都相同的字符串我們稱之為回文串。例如,『racecar』就是回文的,『fastcar』就不是。對一個字符序列的劃分即:分成一堆(至少一個)非空不相交的連續字符串,使它們連起來就是原來的字符序列。例如,『race』,『car』就是把『racecar』劃分成兩組。給定一個字符串,我們總能找到一種劃分使得每個子串都是回文串!(大不了一個字母算一個子串)

Given this observation it is natural to ask: what is the minimum number of groups needed for a given string such that every group is a palindrome?For example:

『racecar』 is already a palindrome, therefore it can be partitioned into one group.

『fastcar』 does not contain any non-trivial palindromes, so it must be partitioned as (『f』, 『a』, 『s』, 『t』, 『c』, 『a』, 『r』).

『aaadbccb』 can be partitioned as (『aaa』, 『d』, 『bccb』).

求:使得每個子串都是回文串的最小劃分組數。

例如,『racecar』本身就是個回文串所以它的答案是1組;『fastcar』不含回文子串,只能一個字母一個字母地分,答案為7組;『aaadbccb』最優可以分成『aaa』,『d』,『bccb』3組。

InputInput begins with the number n of test cases. Each test case consists of a single line of between 1 and 1000 lowercase letters, with no whitespace within..

最先輸入測試組數n。每組給出一個長度1~1000的小寫字母串,中間沒有空格。

OutputFor each test case, output a line containing the minimum number of groups required to partition the input into groups of palindromes.

對於每組測試,輸出可劃分的最少組數。

Sample Input3

racecar

fastcar

aaadbccb

Sample Output1

7

3

思路:

假如我遍歷一遍字符串 ----> 強如『fastcar』的話只能一個字母一個字母地苦逼+1,那麼有回文子串時,差異是如何產生的呢? ----> 就說racecar吧。走到race的時候還是+1模式,再走一步到c的時候發現跟前面的ce能湊個cec ----> 我們用dp數組表示結果,dp[racec]本來等於dp[race]+1,由於找到了回文子串cec,所以變成了min( dp[race]+1, dp[ra]+1 ) ----> 由於我們不知道當前字母最早可以伸展到哪裡去跟別人結合為回文子串,所以可以暴力掃一遍前面的 ----> 至於回文串,一邊掃一遍判斷也可以,預處理也可以,關鍵是複雜度。預處理可以枚舉回文串中心然後向左右伸展得到(j,i)是不是回文串,可以以n的複雜度求解,這樣dp的過程也是n。一邊dp一邊判斷大概是n的複雜度,我不知道怎麼就過了我複雜度算錯了?……

最開始瞎寫的代碼1:20ms

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>usingnamespacestd;int T;int dp[1001];char str[1001];boolispalindrome(int start, int end){for (int i = start; i < (start+end+1)/2; i++)if (str[i] != str[start+end-i])returnfalse;returntrue;}intmain(){scanf("%d", &T);while (T--) {scanf("%s", str+1);int len = strlen(str+1);for (int i = 1; i <= len; i++) { dp[i] = dp[i-1] + 1;for (int j = 1; j <= i-1; j++)if (ispalindrome(j, i))//[j,i]是不是回文 dp[i] = min(dp[i], dp[j-1] + 1); }printf("%d\n", dp[len]); }}

按照上面瞎改的代碼2:20ms

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>usingnamespacestd;int T;int dp[1001];char str[1001];bool ispalindrome[1001][1001];intmain(){scanf("%d", &T);while (T--) {scanf("%s", str+1);int len = strlen(str+1);memset(ispalindrome, false, sizeof(ispalindrome));memset(dp, 0x3f, sizeof(dp));//預處理for (int i = 1; i <= len; i++) {for (int l = i, r = i; str[l] == str[r] && l >= 1 && r <= len; l--, r++) ispalindrome[l][r] = true;for (int l = i, r = i+1; str[l] == str[r] && l >= 1 && r <= len; l--, r++) ispalindrome[l][r] = true; }//dp dp[0] = 0;for (int i = 1; i <= len; i++)for (int j = 1; j <= i; j++)if (ispalindrome[j][i])//[j,i]是不是回文 dp[i] = min(dp[i], dp[j-1] + 1);printf("%d\n", dp[len]); }}

溫馨提示

如果你喜歡本文,請分享到朋友圈,想要獲得我。

ACM算法日常

點讚的時候,請寵溺一點

相關焦點

  • leetcode647_go_回文子串
    題目給定一個字符串,你的任務是計算這個字符串中有多少個回文子串。具有不同開始位置或結束位置的子串,即使是由相同的字符組成,也會被視作不同的子串。示例 1:輸入:&34; 輸出:3解釋:三個回文子串: &34;, &34;, &34;示例 2:輸入:&34; 輸出:6解釋:6個回文子串: &34;, &34;, &34;, &34;, &34;, &34;提示:輸入的字符串長度不會超過 1000 。
  • leetcode132_go_分割回文串II
    題目給定一個字符串 s,將 s 分割成一些子串,使每個子串都是回文串。返回符合要求的最少分割次數。示例:輸入: &34;輸出: 1解釋: 進行一次分割就可將 s 分割成 [&34;,&34;] 這樣兩個回文子串。
  • leetcode516_go_最長回文子序列
    題目給定一個字符串 s ,找到其中最長的回文子序列,並返回該序列的長度。可以假設 s 的最大長度為 1000 。示例 1:輸入:&34;輸出:4一個可能的最長回文子序列為 &34;。示例 2:輸入:&34;輸出:2一個可能的最長回文子序列為 &34;。
  • 求最長回文子串算法——馬拉車算法
    在上面例子中,最長回文子串是"#a#b#b#a#",它以arr[6]為中心,半徑是5,其代表的原始字符串是"abba",而"abba"的長度為4,可以通過5減去1得到,是字符串"cabbaf"中的最長回文子串,那麼我們是不是可以得出最長回文半徑和最長回文子串長度之間的關係?
  • 大廠筆試題——LeetCode05最長回文子串
    s,找到 s 中最長的回文子串。示例 2:輸入: &34;輸出: &34;普通暴力分析:求最長的回文串而回文串又有奇數串和偶數串兩種形式,我們只需要對有所情況從左到右進行枚舉,然後返回最長的串即可。在編寫代碼的同時注意邊界的問題不能越界。返回合理編號字符串。不要用String類型進行拼湊,因為String是不可變類每個拼湊都會生成一個新的字符串,多個拼湊會導致效率非常低下。
  • 最長回文字符串三種解法
    當給定很長的字符串時,如何快速獲取到最長的回文字符串,這也是大廠比較常見的算法面試題,那麼這裡給出三種解法。1.暴力窮舉法思路:即遍歷每種子字符串,然後判斷該子字符串是否為回文(即前半部分是否等於後半部分),時間複雜度為O(n*n*n)
  • 回文字符串問題分析
    首先最簡單的方法,暴力窮舉所有的子串,然後分別利用上述的方法進行判斷即可。遍歷+判斷,窮舉法總的時間複雜度為O(n^3).主要原因是其存在著大量重複的判斷,比如當substring(i,j)不是回文串時,我們可以確定substring(i-1,j+1)一定不是回文串,不用進行判斷即可。由此我們考慮構造一個從中心節點雙向探測的方法來獲取最長的回文子串,即判斷每一個中心節點可以構成的回文的最長串。現在的主要問題是,一共有多少個這樣的中心節點呢?答案是2*n-1個,這是考慮了奇數回文和偶數回文的兩種不同情況,如下圖所示。
  • 每日一道編程題(145):最長回文子串Ⅴ
    每日編程中遇到任何疑問、意見、建議請公眾號留言或直接撩Q474356284(備註每日編程)今日問題:給定一個字符串s,找到s中最長的回文子串。你可以假設s 的最大長度為1000。示例2:輸入:"cbbd"輸出:"bb"解決方法:C++代碼:Java代碼:明日題目預告:Z字形變換將字符串"PAYPALISHIRING"以Z字形排列成給定的行數:P A H NA P L S I I G
  • leetcode214_go_最短回文串
    題目給定一個字符串 s,你可以通過在字符串前面添加字符將其轉換為回文串。找到並返回可以用這種方式轉換的最短回文串。string(s[j]) + res } return res}func add(s string) string { var res []rune for _, v := range s { res = append(res, &&39;39;) return string(res)}總結Hard題目,回文字符串題目
  • 網際網路公司高頻面試題目「回溯算法」:分割回文串
    給定一個字符串 s,將 s 分割成一些子串,使每個子串都是回文串。首先判斷這個子串是不是回文,如果是回文,就加入在vector<string> path中,path用來記錄切割過的回文子串。
  • leetcode之最長回文串
    序本文主要記錄一下leetcode之最長回文串題目給定一個包含大寫字母和小寫字母的字符串,找到通過這些字母構造成的最長的回文串比如 "Aa" 不能當做一個回文字符串。注意:假設字符串的長度不會超過 1010。示例 1:輸入:"abccccdd"輸出:7解釋:我們可以構造的最長的回文串是"dccaccd", 它的長度是 7。
  • 370,最長公共子串和子序列
    我們一眼就能看出他們的最長公共子串是&34;,長度是2。但如果字符串特別長的話就不容易那麼觀察了。1,暴力求解:暴力求解對於字符串比較短的我們還可以接受,如果字符串太長實在是效率太低,所以這種我們就不再考慮2,動態規劃:我們用一個二維數組dp[i][j]表示第一個字符串前i個字符和第二個字符串前j個字符組成的最長公共字符串的長度。
  • 大廠面試題LeetCode08字符串轉整數&&09迴文數(優化)
    這裡個人使用遍歷字符串數字字符時候將其與&39;字符差轉換成數字進行計算,當超出int範圍直接停止。描述:迴文數判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。分析:此題比較簡單,需要考慮以下幾點:不能是負數,負數不滿足迴文數的要求考慮奇數偶數長度數字會文性提供兩種方法:第一種將數字轉成字符串,從中間向兩側拓展比較
  • 用Python求最長子串長度快速版
    哈嘍大家好,周二也是令人愉快的一天啊,今天天氣不錯,坐在窗戶旁邊邊曬太陽邊寫文章,再泡杯熱茶,真是舒服美好,廢話不多說,今天說一下Python求最長子串長度,希望對大家有作用,raksmart伺服器。給定一個字符串,求它最長的回文子串長度,例如輸入字符串'35534321',它的最長回文子串是'3553',所以返回4。
  • leetcode87_go_擾亂字符串
    題目給定一個字符串 s1,我們可以把它遞歸地分割成兩個非空子字符串,從而將其表示為二叉樹。下圖是字符串 s1 = &34; 的一種可能的表示形式。給出兩個長度相等的字符串 s1 和 s2,判斷 s2 是否是 s1 的擾亂字符串。
  • 回文排列
    回文串是指正反兩個方向都一樣的單詞或短語。排列是指字母的重新排列。回文串不一定是字典當中的單詞。true(排列有"tacocat"、"atcocta",等等)題目思考什麼字符串是回文串的排列
  • 回文日裡說回文
    我們從右往左讀,和從左往右讀,都是同一組數字,和文學當中的回文現象是一致的,叫作「回文日」(un jour palindrome)也很貼切。記得兩三周前,媒體熱議的話題還是「民政局2020年2月2日該不該加班?」