【UVa11584】劃分成回文串
阿新 • • 發佈:2018-08-18
回文串 優秀 nbsp als template 都是 else rac bool
題目描述
給一個字符串, 要求把它分割成若幹個子串,使得每個子串都是回文串。問最少可以分割成多少個。 字符串長度不超過1000。
例如:
“racecar”本身就是回文串,答案為1
“fastcar”,答案為7,分成的7個回文串為"f", "a", "s", "t", "c", "a", "r"
“aaadbccb”,答案為3,分成的3個回文串為"aaa", "d", "bccb"
輸入
第一行一個數T。接下來T行,每行一個字符串。
輸出
對於每個字符串輸出答案。
樣例輸入
3
racecar
fastcar
aaadbccb
樣例輸出
1
7
3
題解
dp[i] 為字符串中 1~i 劃分成最少回文串的個數。則:
dp[ i ]=min( dp[ j ] + 1 ) 其中,s[ j+1 -> i ] 為回文串
於是我們發現時間復雜度來到了O(n3),不夠優秀。考慮降低復雜度,我們用O(n2)的時間預處理出 s[ i --> j ] 是否為回文串
然後總時間復雜度降為 O(n2)。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> usingnamespace std; #define ll long long const int maxn=1000+10; char a[maxn]; int dp[maxn],l,lef,rig; bool p[maxn][maxn]; template<typename T>void read(T& aa) { char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<‘0‘||cc>‘9‘)&&cc!=‘-‘) cc=getchar(); if(cc==‘-‘) ff=-1,cc=getchar();while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); aa*=ff; } int main(){ memset(dp,127,sizeof(dp)); memset(p,false,sizeof(p)); scanf("%s",a+1); l=strlen(a+1); for(int i=1;i<=l;i++){ lef=i;rig=i; while(lef>0&&rig<=l){ if(a[lef]==a[rig]) p[lef][rig]=true; else break; lef--;rig++; } } for(int i=1;i<l;i++){ lef=i;rig=i+1; while(lef>0&&rig<=l){ if(a[lef]==a[rig]) p[lef][rig]=true; else break; lef--;rig++; } } dp[1]=1;dp[0]=0; for(int i=2;i<=l;i++) for(int j=0;j<i;j++){ if(p[j+1][i]) dp[i]=min(dp[i],dp[j]+1); } cout<<dp[l]<<endl; return 0; }
【UVa11584】劃分成回文串