题目很简单
一个字符串如果从左往右和从右往左读的结果是一样的,则称为回文字符串。写程序找出给定字符串的最长回文子串。例如字符串 abcbabcb,有多个回文字串 bcb,bab,cbabc,bcbabcb 等,其中最长回文子串为 bcbabcb。
有多种解法
1.中心扩展
思路就是枚举回文串中心对称点,注意要区分奇偶情况即可。
int solve()
{
int len = strlen(a);
for(int i=1;i<len-1;i++){
int m1,m2;
m1=1;
m2=0;
int j=1;
while(i-j>=0&&i+j<len&&a[i-j]==a[i+j]){
m1+=2;
j++;
}
if(i+1<len&&a[i]==a[i+1]){
m2=2;
j = 1;
while(i-j>=0&&i+j+1<len&&a[i-j]==a[i+j+1]){
m2+=2;
j++;
}
}
d[i] = max(m1,m2);
}
int ans = 1;
for(int i=1;i<len-1;i++){
ans = max(ans,d[i]);
}
return ans;
}
2.DP法
dp[i][j]表示的是字符串中下标i到j的子串a[i,j]是否为回文串,1表示是。
易知,当a[i]==a[j]时,若a[i,j]为回文串,a[i+1,j-1]也是回文串;否则,a[i+1,j-1]也不是回文串
初始时dp[i][i]=1;当a[i]==a[i+1]时,dp[i][i+1]=1。
要注意的是第一重循环枚举的不是起始点,而是长度
因为dp[i][j]是由dp[i+1][j-1]推出的,只有通过先枚举长度,才能够得到所有会用到的dp[i+1][j-1]。
int solve()
{
int len = strlen(a);
int ans = 1;
for(int i=0;i<len;i++){
dp[i][i]=1;
if(i!=len-1&&a[i]==a[i+1]){
dp[i][i+1]=1;
ans = 2;
}
}
for(int l=3;l<=len;l++){
for(int i=0;i+l-1<len;i++){
int j = i+l-1;
if(a[i]==a[j]){
dp[i][j] = dp[i+1][j-1];
if(dp[i][j]) ans = l;
}
else{
dp[i][j] = 0;
}
}
}
return ans;
}