标签:string desire -- ret strlen 推导 \n iostream example
A palindrome partition is the partitioning of a string such that each separate substring is a palindrome.
For example, the string "ABACABA" could be partitioned in several different ways, such as {"A","B","A","C","A","B","A"}, {"A","BACAB","A"}, {"ABA","C","ABA"}, or {"ABACABA"}, among others.
You are given a string s. Return the minimum possible number of substrings in a palindrome partition of s.
Input
Input starts with an integer T (≤ 40), denoting the number of test cases.
Each case begins with a non-empty string s of uppercase letters with length no more than 1000.
Output
For each case of input you have to print the case number and the desired result.
Sample Input
3
AAAA
ABCDEFGH
QWERTYTREWQWERT
Sample Output
Case 1: 1
Case 2: 8
Case 3: 5
题意:给出一个字符串,将该字符串切割成若干个回文串,使切割后的回文串数最小,求这个回文串数
题解:这道题其实在之前DP百题大过关中已经出现过了,复杂度是n^3的,今天写的时候突然糊出了n^2的做法,再记录一下
首先是状态转移方程的推导
f[i]表示1-i之间的最小分割数,很显然只有当i~j是回文串的时候i-1才能转移到j,贡献为1
所以状态转移方程为
f[j]=max{f[i-1]+1}(i~j为回文串)
这个转移方程是n^2的,但上次写的时候在里面加入了O(N)的回文串判断,复杂度变成了O(N^3)
如今想想,其实是不是回文串这东西是可以预处理的
枚举每一个中点,向两边拓展,可以在O(N^2)中处理出每一段i~j是否是回文串
然后就有了O(N^2)复杂度的DP
代码如下:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int c[1010][1010],n,f[1010]; char s[1010]; void get(int l,int r) { while(l>0&&r<=n) { if(s[l]==s[r]) { c[l][r]=1; } else { return ; } l--; r++; } } int main() { int t,ttt=0; scanf("%d",&t); while(t--) { ttt++; memset(f,0x3f,sizeof(f)); memset(c,0,sizeof(c)); scanf("%s",s+1); n=strlen(s+1); for(int i=1; i<=n; i++) { get(i,i); get(i,i+1); } f[0]=0; for(int i=1; i<=n; i++) { for(int j=1; j<=i; j++) { if(c[j][i]) { f[i]=min(f[i],f[j-1]+1); } } } printf("Case %d: %d\n",ttt,f[n]); } }
大佬们的常数都好优越啊,N^3跑的都比N^2快qwq
LightOJ 1044 Palindrome Partitioning(简单字符串DP)
标签:string desire -- ret strlen 推导 \n iostream example
原文地址:https://www.cnblogs.com/stxy-ferryman/p/9280830.html