[ UVA11584 ],DP

题意

当一个字符串正序和反序是完全相同时,我们称之为“回文串”。例如“racecar”就是一个回文串,而“fastcar”就不是。现在给一个字符串s,把它分割成若干个互不相交的回文子串,求分割的回文子串的最少个数。


分析


CODE

scanf("%s", s + 1);//下面要用到字符的第一位跟前一位比较,从1开始方便初始化,c++没有负数数组。
        s[0] = '0';//填上第一位,如果不填strlen算出长度就是0
        int len = strlen(s)-1;
        memset(sum,0,sizeof(sum));//多组数据要初始化。
        //求sum有三种情况
        for(int i=1; i <= len; i++)
        {
            int j,k;
            sum[i][i]=1;//每个单独的字符是回文串
            for(j =i, k = i+1 ; j >= 1 && k <= len ; j--, k++)
            {//如果是偶数个的回文串
                if(s[j] == s[k] )
                {
                    if(j+1<=k-1 && sum[j+1][k-1])//不能j+1,k-1后j跑到k前面去了
                    sum[j][k]=1;
                    if(k-j==1)//如果只相差1就是两个相邻的字符
                    sum[j][k]=1;
                }

               //if(sum[j][k]) cout<<j<<"->"<<k<<" "<<sum[j][k]<<endl;
            }
            for(j = k = i ; j >= 1 && k <= len ; j--, k++)
            {//如果是奇数的回文串
                if(s[j] == s[k] &&k!=j && sum[j+1][k-1])
                {
                    sum[j][k]=1;
                }
               //if(sum[j][k]) cout<<j<<"->"<<k<<" "<<sum[j][k]<<endl;
            }
        }
        memset(f,12,sizeof(f));//初始化为无穷大
        f[0]=0;//方便更新状态
        for(int i=1;i<=len;i++)
        {
            for(int j=1;j<=i;j++)
            if(sum[j][i])f[i]=min(f[i],f[j-1]+1);
        }
        cout<<f[len]<<endl;;

猜你喜欢

转载自blog.csdn.net/k42946/article/details/81128748