迴文字串 (動態規劃,最長公共子序列)
阿新 • • 發佈:2019-02-13
迴文字串
時間限制:3000 ms | 記憶體限制:65535 KB 難度:4- 描述
- 所謂迴文字串,就是一個字串,從左到右讀和從右到左讀是完全一樣的,比如"aba"。當然,我們給你的問題不會再簡單到判斷一個字串是不是迴文字串。現在要求你,給你一個字串,可在任意位置新增字元,最少再新增幾個字元,可以使這個字串成為迴文字串。
- 輸入
- 第一行給出整數N(0<N<100)
接下來的N行,每行一個字串,每個字串長度不超過1000. - 輸出
- 每行輸出所需新增的最少字元數
- 樣例輸入
-
1 Ab3bd
- 樣例輸出
-
2
-
剛開始看到這道題,看了一會沒看出頭緒,然後看人家說是要用動態規劃裡面的最長公共子序列,可是還是想不出為什麼。後來同學同學問我這道題,就仔細的想了想。結果發現還真是。
-
思路:題目中是要求將字串補成迴文串時最少補充的字元。那麼我們可以這樣想,我們先有一個迴文串,然後故意去掉幾個。。。就成了題目中的測試案例。
-
然後呢,假設去掉的那些字元我們保留為空格,我們想,既然之前是迴文的,當我們反轉過來背去掉剩下的,然後去掉空格,必然會有些字元還是匹配的,這部分匹配的就是不用動的部分,一個字串當作模式串,一個當作匹配串,從頭到尾匹配,總有一種情況下匹配的字元達到最大,這便是我們把他們變回迴文串時不用改動的最大數值,然後根據題意,只要我們拿字串的總長度減去這個數,便是需要改動的最少個數。也就轉化成了求最長公共子序列問題。
-
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
-
對案例:asdfgg 進行的測試。#include<iostream> #include<string> #include<cstring> using namespace std; char *reverse( char a[]) { char *b=new char[1005]; int t=strlen(a); int i,j; for(i=t-1,j=0;i>=0;j++,i--){ b[j]=a[i]; } return b; } int dp[1000][1000]; int main() { int n; cin>>n; while(n--) { char a[1005]; cin>>a; int str = strlen(a); string b=reverse(a); //cout<<b<<endl; for(int i =0;i <= str;i ++){ for(int j =0 ;j <= str; j++){ if(i == 0||j == 0) dp[i][j]=0; else if(b[i-1] == a[j-1]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } /*for(int i = 0; i <= str; i ++){ for(int j = 0;j <= str; j++){ cout<<dp[i][j]<<" "; } cout<<endl; }*/ cout<<str-dp[str][str]<<endl; } return 0; }
-
看下圖,理解最長公共子序列
-
案例是:ACDDEB和ADC