問題 A 字串 最長回文子串

2021-09-27 12:20:13 字數 1699 閱讀 6475

輸入乙個字串,求出其中最長的回文子串。子串的含義是:在原串中連續出現的字串片段。回文的含義是:正著看和倒著看相同。如abba和yyxyy。在判斷回文時,應該忽略所有標點符號和空格,且忽略大小寫,但輸出應保持原樣(在回文串的首部和尾部不要輸出多餘字元)。輸入字串長度不超過5000,且佔據單獨的一行。應該輸出最長的回文串,如果有多個,輸出起始位置最靠左的。

一行字串,字串長度不超過5000。

字串中的最長回文子串。

confuciuss say:madam,i'm adam.
madam,i'm adam

樣例說明:madam,i'm adam去掉空格、逗號、單引號、忽略大小寫為madamimadam,是回文。

演算法分析一:

首先解決「判斷時忽略標點,輸出進卻要按原樣」的問題? 可以用乙個簡單的方法:預處理。構造乙個新字串,不包含原來的標點符號,而且所有字元變成大寫(順便解決了大小寫的問題)。用到的函式:

(1)isalpha(c)用來檢查c是否為字母,如果是字母,則返回1;否則返回0。

(2)isdigit(c)用來檢查c是否為數字(0~9),如果是數字,則返回1;否則返回0。

(3)toupper(c)用來將c字元轉換為大寫字母,返回c對應的大寫字母。

(4)tolower(c)用來將c字元轉換為小寫字母,返回c對應的小寫字母。

下面來列舉回文串的起點和終點,然後判斷它是否真的是回文串。

int max=0;

for(i = 0; i < m; i++)

for(j = i; j < m; j++)

if(s[i..j]是回文串 && j-i+1 > max) max = j-i+1;

「當前最大值」變數max,它儲存的是目前為止發現的最長回文子串的長度。如果串s的第i個字元到第j個字元(記為s[i..j])是回文串,則檢查長度j-i+1是否超過max。

判斷s[i..j]是否為回文串的方法如下:

int ok = 1;

for(k = i; k <= j; k++)

if(s[k] != s[i+j-k])   ok = 0;

s[k]的「對稱」位置是s[i+j-k],因為只要一次比較失敗,就應把標記變數ok置為0。

最後的問題:原樣輸出。

由於在求max值時,不知道s[i]和s[j]在原串buf中的位置。因此,必須增加乙個陣列p,用p[i]儲存s[i]在buf中的位置。在預處理得到,然後在更新max的同時把p[i]和p[j]儲存到x和y,最後輸出buf[x]到buf[y]中的所有字元。

不足:當輸入字串較長時,容易超時,因列舉回文起點和終點,迴圈過多。

動態規劃

#includeusing namespace std;

const int maxn = 5001;

struct node

s[maxn];

int main()}}

// 狀態轉移方程

for(int l=3; l<=len; l++) //列舉子串的長度}}

}for(int i=left; i<=right; i++)

cout<< endl;

}return 0;

}

字串 最長回文子串

最長回文子串 回文子串 即正著看和倒著看相同的子串,如 abcba yyxyy。由於此類題目為面試筆試常考題目,所以現在就來整理一下啦。1 暴力求解法 最直接的想法就是暴力求解,但是我們可以看到下面的 時間複雜度是o n 3 string findlongeststring string str 暴...

字串 最長回文子串

介紹一下幾個概念 就是從左往右和從右往左讀是一樣的。就如標語 我為人人,人人為我 子串,顧名思義,就是在原字串中的子集,就叫子串。串就是不能分割的,就是連在一起,這個要區別與子串行,子串行就是一段 一段的。列舉各個起點和終點,然後進行判斷該子串是否為回文,最後就是更新最長的回文串。列舉起點和終點 o...

字串 最長回文子串

給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。示例 1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例 2 輸入 cbbd 輸出 bb 思路 用manacher class solution int max 1 int res 0 儲存最...