寫這個看似簡單的題目才發現自己原來毛都不會(╯‵□′)╯︵┻━┻,加上網上有很多的解析其實講的都不準確,導致了很多理解上的錯誤
這道題就是求字符串s和字符串的逆序串s’的最長公共“子序列”,而並非所謂的最長“子串”,一般來說兩個子串一定是連續的一段字符,而子序列可以是不連續的……
然後問題來了,怎麼求兩個子串的最長公共子序列呢,這裏用的是動態規劃的方法,用數組dp[i][j]來記錄兩個字符串長度爲i和j的前綴的最長公共子序列,然後狀態轉移方程爲如果str1[i] == str2[j]那麼dp[i][j] = dp[i-1][j-1]+1,否則dp[i][j] = max(dp[i-1][j],dp[i][j-1])
p.s. 如果要求的是最長公共子串,那麼當str1[i]!=str1[j]的時候,令dp[i][j] = 0就可以了,這裏dp[i][j]表示的是兩子串的最長公共後綴,所有前綴的最長公共後綴就是最長公共子串。
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
#define maxn 5001
int n;
char str1[maxn]={0};
char str2[maxn]={0};
short dp[2][maxn]={0};
int mymax = 0;
int main(){
scanf("%d",&n);
scanf("%s",&str1);
for(int i=0;i<n;++i){
str2[i] = str1[n-i-1];
}
str2[n] = '\0';
//printf("%s\n",str2);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(str1[i-1]==str2[j-1])
dp[i%2][j] = dp[(i-1)%2][j-1]+1;
else
dp[i%2][j] = max(dp[(i-1)%2][j],dp[i%2][j-1]);
if(dp[i%2][j]>mymax)
mymax = dp[i%2][j];
}
}
printf("%d\n",n-mymax);
//system("pause");
return 0;
}