timus 1635. Mnemonics and Palindromes URAL 解題報告

timus   1635. Mnemonics and Palindromes   URAL 解題報告

題目大意,面試爲了記住更多的單詞,貌似,就想將一行字符串(由26個小寫字母寫組成的),分成幾個迴文串的形式! 
輸出個數和迴文串!
例如:
pasoib
6
p a s o i b
zzzqxx
3
zzz q xx
wasitacatisaw
1
wasitacatisaw

這個題貌似不難是很簡單的DP,但是當時當時有一個細節沒想好,導致錯了N遍了……   難度才200+啊,當時我用一位數組dp[i]表示前i個字符最少能構成多少個迴文串啊,狀態轉移是dp[i]=dp[j]  j<i  並且j--i是迴文串,當時想既然j--i是一個迴文串了,那麼個數就等於dp[j],不用再增加了,後來看了dicuss裏面的討論才知道自己錯在哪裏了……   
0--j可能是一個迴文串,j--i可能是一個迴文串,但是dp[i]!=dp[j]   ,只能說明j-i是一個,應該是dp[j-1]+1 纔對啊……

改完這裏之後又發現超時,原因是我的算法是O(n^3)的算法,每次判斷是不是迴文串就是一個O(n)的算法,後來與處理了一下,枚舉中點,並且將這個也看做時中點的左側點……      預處理接近O(n^2)  但是沒超時,我很鬱悶,後來才知道,預處理雖然比簡單的判斷迴文串的函數複雜,但是隻調用了一次而已,而簡單的判斷迴文串的On的算法是嵌套在裏面的,而現在這個是並列的,是兩個O(n^2) 算法……

一個破題調試一天了,鬱悶,得長記性了……

找不到問題的時候應該仔細研究下代碼並且嘗試自己出出測試數據……
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
#define mem(a,v)  memset(a,v,sizeof(a))
#define N 4004


char ch[N];

int dp[N];
bool f[N][N];
short father[N];

void init()
{///預處理,雖然效率不是很高,但畢竟只調用一次啊
    memset(f,-1,sizeof(f));
    int len=strlen(ch);
    int x,y;
    f[0][0]=1;
    f[len-1][len-1]=1;
    for(int i=0;i<len-1;++i)
    {///枚舉中點,這裏的中點也有可能是中相鄰的點;就是說1221這個迴文串沒有中點,2只能是中點相鄰點點
        f[i][i]=1;
        x=y=i;
        while(x>=0&&y<len)
        {
            if(ch[x]!=ch[y])
            {
                while(x>=0&&y<len)
                {
                    f[x--][y++]=0;
                }
            }else f[x--][y++]=1;
        }

         x=i;y=i+1;
        while(x>=0&&y<len)
        {
            if(ch[x]!=ch[y])
            {
                while(x>=0&&y<len)
                {
                    f[x--][y++]=0;
                }
            }else f[x--][y++]=1;
        }
    }
}

bool slove(int x,int y)
{///判斷x--y串中
    bool flag=true;
    while(true)
    {
         if(ch[x++]!=ch[y--]){flag=false;break;}
         if(x>y)break;
    }
    return flag;
}

int main()
{
    mem(dp,0x3f3f);

    scanf("%s",&ch);
    init();
    int len=strlen(ch);
    dp[0]=1;
    for(int i=0;i<len;++i)
    {
        dp[i]=i+1;
        father[i]=i;
    }
    //cout<<dp[3]<<endl;
    for(int i=1;i<len;++i)
    {
        for(int j=0;j<i;++j)
        {///尋找回文串
            if(f[j][i])
            {
                if(j==0){ dp[i]=1; father[i]=0;}
                else if(dp[i]>dp[j-1]+1){ dp[i]=dp[j-1]+1; father[i]=j;}///這裏坑死人了
//                if(f(j,i)) cout<<dp[i]<<"==="<<j<<" ====!!!!!!!============ "<<i<<endl;
            }
        }if(dp[i]>dp[i-1]+1){ dp[i]=dp[i-1]+1 ;father[i]=i; }
    }


    //cout<<"father"<<father[len-1]<<endl;
    stack<char> sta;
    int cnt=0;
    for(int i=len-1;i>=0;--i)
    {
        int len0=father[i];
        for(int k=i;k>=len0;k--)
        {
            sta.push(ch[k]); i=k;
        }cnt++;
        if(i!=0)sta.push(' ');
    }
    //if(cnt!=dp[len-1])while(true){};
    cout<<cnt<<endl;
    while(!sta.empty())
    {
        cout<<sta.top(); sta.pop();
    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章