【IOI2000】【洛谷1435】迴文字串

問題描述

迴文詞是一種對稱的字符串。任意給定一個字符串,經過插入若干字符,均可以變成迴文詞。此題的任務是,求出將給定字符串變成迴文詞所須要插入的最少字符數。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 }
相關文章
相關標籤/搜索