题目描述
如果一个字符串S是由两个字符串T连接而成,即S = T + T, 我们就称S叫做平方串,例如"",“aabaab”,"xxxx"都是平方串.
牛牛现在有一个字符串s,请你帮助牛牛从s中移除尽量少的字符,让剩下的字符串是一个平方串。换句话说,就是找出s的最长子序列并且这个子序列构成一个平方串。
输入描述:
输入一个字符串s,字符串长度length(1 ≤ length ≤ 50),字符串只包括小写字符。
输出描述:
输出一个正整数,即满足要求的平方串的长度。
求解思路
动态规划(DP)
这个问题其实就是一个求解最大子串的问题。可以依次把字符串分为两个子串,求解两个子串间的最大子串,最大子串的长度乘以2即为最后结果。
最大子串的求解可以按照以下递推公式进行求解
c
[
i
,
j
]
=
{
0
i
=
0
or
j
=
0
c
[
i
−
1
,
j
−
1
]
+
1
i
,
j
>
0
and
x
i
=
y
j
max
(
c
[
i
,
j
−
1
]
,
c
[
i
−
1
,
j
]
)
i
,
j
>
0
and
x
i
≠
y
j
c [ i , j ] = \left\{ \begin{array} { c c } { 0 } & { i = 0 \text { or } j = 0 } \\ { c [ i - 1 , j - 1 ] + 1 } & { i , j > 0 \text { and } x _ { i } = y _ { j } } \\ { \max ( c [ i , j - 1 ] , c [ i - 1 , j ] ) } & { i , j > 0 \text { and } x _ { i } \neq y _ { j } } \end{array} \right.
c[i,j]=⎩⎨⎧0c[i−1,j−1]+1max(c[i,j−1],c[i−1,j])i=0 or j=0i,j>0 and xi=yji,j>0 and xi̸=yj
对于如何求解最大子串问题,个人认为博客https://blog.youkuaiyun.com/someone_and_anyone/article/details/81044153讲的很清楚,可以借鉴。
代码实现
#include"iostream"
#include"vector"
#include"string"
using namespace std;
int LCS(string s1, string s2)
{
vector<vector<int>> dp(s1.size()+1,vector<int>(s2.size()+1));
int l1=s1.size();
int l2=s2.size();
for(int i=0;i<l1+1;i++)
for(int j=0;j<l2+1;j++)
{
if(i==0||j==0)
dp[i][j]=0;
else if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=(dp[i-1][j]>dp[i][j-1])?dp[i-1][j]:dp[i][j-1];
}
return dp[l1][l2];
}
int main()
{
string s;
cin>>s;
int max=0;
int n=s.size();
for(int i=1;i<n-1;i++)
{
string s1=s.substr(0,i);
string s2=s.substr(i,n-i);
int t1;
t1=LCS(s1,s2);
max=(max>t1)?max:t1;
}
cout<<max*2;
return 0;
}