D1. Prefix-Suffix Palindrome (Easy version)
easy版本 我们只需要n2 dp预处理出快速判断回文串
然后我们再通过双指针O(n)求解最大串
int dp[5010][5010];
void solve(){
string s;cin>>s;
int n=s.size();s=')'+s;
for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)dp[i][j]=0;
for(int i=1;i<=n;i++){
dp[i][i]=1;
if(i!=1&&s[i]==s[i-1])dp[i-1][i]=1;
}
for(int len=3;len<=n;len++){
for(int i=1,j=i+len-1;j<=n;j++,i++){
if(s[i]==s[j])dp[i][j]|=dp[i+1][j-1];
}
}
int ans=0;string S;
for(int i=1;i<=n;i++)if(dp[1][i]){
if(ans<i)S=s.substr(1,i),ans=i;
}
for(int i=1;i<=n;i++)if(dp[i][n]){
if(ans<n-i+1)S=s.substr(i,n-i+1),ans=n-i+1;
}
int l=0;
for(int i=1,j=n;i<j;i++,j--){
if(s[i]!=s[j])break;
else{
int t=0;
for(int k=i+1;k<j;k++)if(dp[i+1][k])t=max(t,k-i);
for(int k=j-1;k>i;k--)if(dp[k][j-1])t=max(t,j-k);
if(ans<i*2+t){
ans=i*2+t;
l=i;
}
}
}
if(!l)cout<<S<<endl;
else{
S.clear();
string r=s.substr(1,l);
S+=r;
int i=l,j=n-l+1,t=0;
string q;
for(int k=i+1;k<j;k++)if(dp[i+1][k]){
if(t<k-i){
t=k-i;
q=s.substr(i+1,t);
}
}
for(int k=j-1;k>i;k--)if(dp[k][j-1]){
if(t<j-k){
t=j-k;
q=s.substr(k,t);
}
}
S+=q;
std::reverse(r.begin(), r.end());
S+=r;
cout<<S<<endl;
}
}
D2. Prefix-Suffix Palindrome (Hard version)
相比于上一个 我们还可以发现的性质就是
我们最开始就可以贪到彻底 直接去找最长的前缀后缀
因为我们不可能前面会有一个很小的前缀后缀with一个字符串 如果是的话这样字符串贪到彻底也是相同的ans
所以我们问题就变成了一个字符串中求最长的前缀/后缀回文串
我们直接O(n)的manacher就可以了
manacher是求出每一个p[i]以i坐标为中心的最长回文半径
我们只要p[i]==i 那么就是最长前缀了不是吗
后缀我们reverse一遍即可
inline int work(string s, int n) {
string ss = "$#";
vector<int>p;
for (int i = 0; i < n; i++) ss += s[i], ss += "#";
p.push_back(1);
int mx = 0, id = 0, ans = 1;
for (int i = 1; i < (int)ss.length(); i++) {
p.push_back(mx > i ? min(p[2*id-i], mx - i) : 1);
while (i + p[i] < (int)ss.length() && ss[i+p[i]] == ss[i-p[i]]) ++p[i];
if (i == p[i]) ans = max(ans, p[i]);
if (i + p[i] > mx) mx = i + p[i], id = i;
}
return ans - 1;
}
void solve(){
string s;cin>>s;int n=s.size();s=')'+s;
int l=0,r=n+1;
for(int i=1,j=n;i<j;i++,j--) {
if (s[i] != s[j])break;
l = i, r = j;
}
string t;
for(int i=l+1;i<r;i++)t.push_back(s[i]);
int ans_l=work(t,r-l-1);
reverse(all(t));
int ans_r=work(t,r-l-1);
if(ans_l>ans_r)reverse(all(t)),swap(ans_l,ans_r);
for(int i=1;i<=l;i++)cout<<s[i];
for(int i=0;i<ans_r;i++)cout<<t[i];
for(int i=l;i>=1;i--)cout<<s[i];
cout<<endl;
}
标签:string,int,Global,Codeforces,mx,ss,ans,Round,dp
From: https://www.cnblogs.com/ycllz/p/16851779.html