【openjudge】切割回文
阿新 • • 發佈:2019-01-03
描述
接下來的 T 行,每一行都包含了一個長度不超過的 1000 的字串,且字串只包含了小寫字母。 輸出 對於每組資料,輸出一行。該行包含一個整數,表示阿福最少切割的次數,使得切割完得到的子串都是迴文的。 樣例輸入
樣例輸出
對於第二組樣例,阿福最少切割 3 次,將原串切割為“a”、“b”、“c”、“d”這四個迴文子串。
對於第三組樣例,阿福不需要切割,原串本身就是一個迴文串。
阿福最近對迴文串產生了非常濃厚的興趣。
如果一個字串從左往右看和從右往左看完全相同的話,那麼就認為這個串是一個迴文串。例如,“abcaacba”是一個迴文串,“abcaaba”則不是一個迴文串。
阿福現在強迫症發作,看到什麼字串都想要把它變成迴文的。阿福可以通過切割字串,使得切割完之後得到的子串都是迴文的。
現在阿福想知道他最少切割多少次就可以達到目的。例如,對於字串“abaacca”,最少切割一次,就可以得到“aba”和“acca”這兩個迴文子串。
接下來的 T 行,每一行都包含了一個長度不超過的 1000 的字串,且字串只包含了小寫字母。 輸出 對於每組資料,輸出一行。該行包含一個整數,表示阿福最少切割的次數,使得切割完得到的子串都是迴文的。 樣例輸入
3 abaacca abcd abcba
1 3 0提示 對於第一組樣例,阿福最少切割 1 次,將原串切割為“aba”和“acca”兩個迴文子串。
對於第二組樣例,阿福最少切割 3 次,將原串切割為“a”、“b”、“c”、“d”這四個迴文子串。
對於第三組樣例,阿福不需要切割,原串本身就是一個迴文串。
其實一直不是很擅長字串動規的題目
其實這道題的思路很簡單。ok是判斷迴文。相當於一個劃分型dp,f[i]表示前i個的最優值。貌似普通的劃分性dp(二維陣列)不能用,會T。
其實用一維陣列和兩重迴圈可以解決。因為如果當前無法滿足的話以後一定也會列舉到。
注意是每一段都是迴文。
【程式碼】
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int t,f[1005],len; char s[1005]; inline bool ok(int l,int r){ int lo=r-l+1; for (int i=l;i<=(l+r)/2;++i) if (s[i]!=s[r-(i-l+1)+1]) return false; return true; } int main(){ scanf("%d\n",&t); while (t--){ gets(s); len=strlen(s); for (int i=len;i>=1;--i) s[i]=s[i-1]; memset(f,127/3,sizeof(f)); for (int i=1;i<=len;++i) if (ok(1,i)) {f[i]=0; continue;} else for (int j=1;j<i;++j) if (ok(j+1,i)) f[i]=min(f[j]+1,f[i]); printf("%d\n",f[len]); } }