1. 程式人生 > >1040. Longest Symmetric String (25)

1040. Longest Symmetric String (25)

ont nba == csdn 找到 tap sun ostream 方法

題目例如以下:

Given a string, you are supposed to output the length of the longest symmetric sub-string. For example, given "Is PAT&TAP symmetric?", the longest symmetric sub-string is "s PAT&TAP s", hence you must output 11.

Input Specification:

Each input file contains one test case which gives a non-empty string of length no more than 1000.

Output Specification:

For each test case, simply print the maximum length in a line.

Sample Input:
Is PAT&TAP symmetric?
Sample Output:
11


題目要求推斷最長的回文,有兩種思路可供選擇。

思路一,從兩頭進行推斷,定義兩個指針start_index和end_index分別指向頭部和尾部,首先固定start_index,讓end_index從最後一個元素向前遍歷,直到碰到start_index。其間對start_index到end_index的範圍進行回文推斷,回文推斷的規則非常easy,假設start和end指向的元素一樣,回文長度length=2,然後start+1。end-1,繼續比較,假設符合則繼續+2。直到start<end不再滿足,註意在這之中僅僅要有一次不符合start指向的元素不等於end指向的元素,累加的長度length都是無效的。都應當輸出1。註意一種情況。假設形如abba這種形式。跳出循環時start = 2、end = 1,length = 4滿足條件。可是假設是形如aba這種形式。start=end=1,length=2。不能得到正確結果,這時候應當推斷是否start==end而且length!=1,則說明是回文、且須要修正,這時候把length+1就可以得到正確結果。


註意一個問題。為了能輸入空格。使用getline(cin,str)來輸入字符串。

代碼例如以下:

#include <iostream>
#include <string>

using namespace std;

string str;

int isRevese(int s, int e){
    int length = 1;
    while(s < e){
        if(str[s] != str[e]) return 1;
        s++;
        e--;
        if(length == 1) length = 2;
        else length += 2;
    }

    if(length != 1 && s == e) length++;

    return length;

}

int main()
{
    getline(cin,str);

    int start_index = 0;
    int end_index = str.length() - 1;
    int max_length = -1;
    int len = 0;

    for(start_index = 0; start_index < str.length(); start_index++){
        for(end_index = str.length() - 1; end_index >= start_index; end_index--){
            len = isRevese(start_index,end_index);
            if(len > max_length){
                max_length = len;
            }
        }
    }
    cout << max_length << endl;
    return 0;
}

思路二,採用中心枚舉法,以每一個字符為中心向兩端枚舉,這種方法最大的問題在於枚舉時對於形如abba的處理十分棘手,由於不管列舉哪個b,都不能找到以b為中心的回文。而其實abba就是回文。

這裏我看到了sunbaigui的巧妙解法,他把全部的字符前面都加一個前導-1,這樣通過以-1為中心枚舉就能夠得到正確的回文了,比如abba變為-1a-1b-1b-1a,通過中間的-1。得到了整個序列,這時候的回文長度是正確長度的2倍,僅僅須要除以2就可以得到正確結果。

這裏直接貼的是sunbaigui的代碼,歡迎去到他的博客。

#include<iostream>
#include<string.h>
#include<vector>

#define Max 10000
int dp[2*Max+1];
char str[Max];

int mmax(int a, int b)
{
	if(a > b) return a;
	else return b;
}
int main()
{
	while(gets(str))
	{
		//memset(dp, -1, sizeof(dp));
		int len = strlen(str);
		//insert special character into str, must not appeared in str
		std::vector<int> magic;
		for(int i = 0; i < len; ++i)
		{
			magic.push_back(-1);//special character
			magic.push_back(str[i]);//character to int
		}
		magic.push_back(-1);
		//enumerate center point for magic vector
		len = (int)magic.size();
		int max = 1;
		for(int i = 1; i < len; ++i)
		{
			int l, r;
			int step = 1;
			for(l = i-1, r = i+1; l >= 0 && r < len; l--, r++)
			{
				if(magic[l] != magic[r])
					break;
				step += 2;
			}
			max = mmax(max, step);
		}

		printf("%d\n", max/2);
	}
	return 0;
}


1040. Longest Symmetric String (25)