迴文詞是一種對稱的字符串。任意給定一個字符串,經過插入若干字符,均可以變成迴文詞。此題的任務是,求出將給定字符串變成迴文詞所須要插入的最少字符數。spa
好比 「Ab3bd」插入2個字符後能夠變成迴文詞「dAb3bAd」或「Adb3bdA」,可是插入少於2個的字符沒法變成迴文詞。code
注:此問題區分大小寫blog
第一行一個整數n(3<=n<=5000)表示字符串的長度字符串
第二行一個長度爲n的字符串string
有且只有一個整數,即最少插入字符數io
5 class
Ab3bd搜索
2db
設讀入的字符串爲s,若是s[i]~s[j]是迴文,那麼s[i+1]~s[j-1]必定也是迴文,知足區間動規的特色。di
設f[i][j]表示s[i]~s[j]變成迴文詞須要插入的最少字符數,當s[i]==s[j]時,f[i][j]=f[i+1][j-1]+1,不然f[i][j]=min(f[i+1][j],f[i][j-1])+1。
我用的是記憶化搜索,當i>j時,因爲是不合法的狀態,我最初返回無窮大,但因爲i>j的狀態只可能從i==j &&s[i]==s[j]轉移過來,因此i>j這個狀態的值實際上是i==j &&s[i]==s[j]這個狀態的值,應該返回0。
1 #include <cstring> 2 #include <cstdio> 3 int n,f[5005][5005]; 4 bool vis[5005][5005]; 5 char s[5005]; 6 int min(int x,int y) 7 { 8 return x<y?x:y; 9 } 10 int dp(int i,int j) 11 { 12 if (i>j) return 0; 13 if (vis[i][j]) return f[i][j]; 14 vis[i][j]=1; 15 if (i==j) return f[i][j]=0; 16 f[i][j]=2e9; 17 if (s[i]==s[j]) f[i][j]=dp(i+1,j-1); 18 f[i][j]=min(f[i][j],min(dp(i+1,j),dp(i,j-1))+1); 19 return f[i][j]; 20 } 21 int main() 22 { 23 int i,j; 24 scanf("%d",&n); 25 scanf("%s",s+1); 26 printf("%d\n",dp(1,n)); 27 return 0; 28 }