22562 Problem A 【字串】最長迴文子串
問題 A: 【字串】最長迴文子串
時間限制: 1 Sec 記憶體限制: 128 MB
提交: 114 解決: 56
[提交][狀態][討論版][命題人:外部匯入]
題目描述
輸入一個字串,求出其中最長的迴文子串。子串的含義是:在原串中連續出現的字串片段。迴文的含義是:正著看和倒著看相同。如abba和yyxyy。在判斷迴文時,應該忽略所有標點符號和空格,且忽略大小寫,但輸出應保持原樣(在迴文串的首部和尾部不要輸出多餘字元)。
輸入
一行字串,字串長度不超過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]中的所有字元。
不足:
演算法分析二:列舉迴文串的“中間”位置i,然後不斷往外擴充套件,直到有字元不同。提示:長度為奇數和偶數的處理方式是不一樣的。
#include<iostream> #include<string> #include<cstdio> #include<cstring> #include<ctype.h> using namespace std; int main() { string s; while (getline(cin, s)) { int p[5000], len = 0, max = 0, x, y; //p儲存str在s中位置,len=str.length() //max=最長迴文子串長度,xy=迴文子串始末位置 char str[5000]; for (int i = 0; i < s.length(); i++) { if (isalpha(s[i])) {//去除標點空格等並轉為大寫字母儲存到str中 str[len] = toupper(s[i]); p[len++] = i;//記錄相應位置 } } //方法一:列舉迴文串從中間向外擴充套件:O(n平方) //奇數 for (int i = 0; i < len; i++) { int num = 1, j; for (j = 1; i + j < len&&i - j>0; j++) { if (str[i + j] == str[i - j]) num += 2; else break; } if (num > max) { max = num; x = p[i - j + 1]; y = p[i + j - 1]; } } //偶數 for (int i = 0; i < len - 1; i++) { int num = 0, j; for (j = 0; i + 1 + j < len&&i - j>0; j++) { if (str[i - j] == str[i + 1 + j]) num += 2; else break; } if (num > max) { max = num; x = p[i - j + 1]; y = p[i + j]; } } /*方法二:從頭到尾暴力列舉(超時40%) for (int i = 0; i < len; i++) { for (int j = i; j < len; j++) { int ok = 1; for (int k = i; k <= (i + j) / 2; k++) { if (str[k] != str[i + j - k]) ok = 0; } if (ok&&j - i + 1 > max) { max = j - i + 1; x = p[i]; y = p[j]; } } } */ for (int i = x; i <= y; i++) { cout << s[i]; } cout << endl; } return 0; }