日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POJ 1159 (DP)

發布時間:2025/3/15 编程问答 10 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 1159 (DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目:http://poj.org/problem?id=1159

思路:

找出原串的最長回文子串,當然這里說的回文子串可以不連續。用原串的長度減去最長回文子串的長度即可得出結果。

設原串a[5001],它的反串為b[5001],求出a和b的最長公共子串的長度(可以不連續),即為回文子串的長度。再用原串長度減去回文子串的長度即可。

用動態規劃求公共子串的長度,m[5001][5001]打表。m[i][j]表示原串a第1個到第i個和反串b第1個到第j個的最長公共子串的長度。所以有兩種情況:

(1)當a[i] = b[j]時,m[i][j]=m[i-1][j-1] + 1;

(2) a[i] != b[j]時,m[i][j]=max(m[i-1][j],m[i][j-1])。

?所以m[len][len]就是最長公共子串的長度。(len為原串的長度)

?

?

算法正確性證明:

比如abcdb,最長回文串是bcb或bdb,長度是3,5-3=2,所以只需插入2個即可。為什么呢???

??? 因為回文串有兩種形式aba或者abba,我們暫且把后面那兩個b看成是一個,這個沒關系的,便于解釋。那么一個字符串就分成了兩類字符了,一個是回文串,一個是非回文串,假設把回文串的中間那個字符記成b,那么b左邊的非回文串和b右邊的非回文串就不可能有交集(如果有,那交集部分就會歸并到回文串里),所以只需要在左邊對稱位置插入b右邊的非回文字符,在右邊插入b左邊的非回文字符。所以要插入的字符個數就是非回文字符的個數,非回文字符就是回文字符串對原字符串的補集,故原串長度減去回文串長度即可得解。

?

代碼:

?

#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 5001char a[N],b[N];unsigned short m[N][N];int main() {int len,i,j,t;while(scanf("%d",&len) != EOF ){scanf("%s",a); t = len -1;for(i = len-1; i >= 0 ; --i)b[t-i] = a[i] ;for(i = 1 ; i <= len ; ++i)for(j = 0 ; j < i ; ++j) m[i][j] = m[j][i] = 0;for(i = 0 ; i <= len ; ++i)m[i][i] = 0;for(i = 1 ; i <= len ; ++i){for(j = 1 ; j <= len ; ++j){if(a[i-1] == b[j-1])m[i][j] = m[i-1][j-1] + 1;elsem[i][j] = m[i-1][j] > m[i][j-1] ? m[i-1][j]:m[i][j-1];}}printf("%d\n",len - m[len][len]);} // system("pause");return 0; }

?

?

開始用 int m[N][N]; 超內存了!用unsigned short 就AC了。

?

看discuss,人家用滾動數組!汗,落伍了。第一次聽說這玩意,于是誠信學習了啊!

?

先貼個最簡單的滾動數組的應用:(求Fabonacci數列的第100個數)

int d[3];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i%3]=d[(i-1)%3]+d[(i-2)%3];
printf("%d",d[99%3]);
注意上面的運算,我們只留了最近的3個解,數組好象在“滾動?一樣,所以叫滾動數組。

好了,這個題就可以用滾動數組+DP AC了。用一個二位的數組m[2][N]。列可以往后展開,行不停的滾動,

滾動方式: i%2,(i-1)%2

代碼:

#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 5001unsigned short m[2][N]; char a[N],b[N];int main() {int len,i,j,t;while(scanf("%d",&len) != EOF ){scanf("%s",a); t = len -1;for(i = len-1; i >= 0 ; --i)b[t-i] = a[i] ;for(i = 0 ; i <= len ; ++i) m[0][i] = m[1][i] = 0;for(i = 1 ; i <= len ; ++i){for(j = 1 ; j <= len ; ++j){if(a[i-1] == b[j-1])m[i%2][j] = m[(i-1)%2][j-1] + 1;elsem[i%2][j] = m[(i-1)%2][j] > m[i%2][j-1] ? m[(i-1)%2][j]:m[i%2][j-1];}}printf("%d\n",len - m[len%2][len]); } //system("pause");return 0; }

?

?

?

?

?

?

轉載于:https://www.cnblogs.com/HpuAcmer/archive/2012/05/03/2481323.html

總結

以上是生活随笔為你收集整理的POJ 1159 (DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。