最长回文
题目大意
就是将两个字符串A和B选择子串进行拼接,然后求通过这样的方法能得到的最长回文串的长度
题解
对字符串A和字符串B各自进行一次manacher,求出p数组
然后枚举回文中心,我们在pA[i]和pB[i]取一个max,表示我们暂时先只取两个串中较长的回文串,然后对于这个回文串,我们可以向两边拓展,因为假设A的回文串的左边的字符不在A的回文串中,但是可以和B右边的字符相同的话,就可以形成回文,边枚举边拓展取最大值即可得到A串和B串取出一段来形成回文串的最大值
#include
using namespace std;
const int maxn=1e5+5;
int n,len;
char s[maxn],a_new[maxn*2],b_new[maxn*2];
int lena[maxn*2],lenb[maxn*2];
void init(char *s_new){
cin>>s;
int j=1;
s_new[0]='$';
s_new[1]='#';
for(int i=0;i<n;i++){
s_new[++j]=s[i];
s_new[++j]='#';
}
s_new[++j]='\0';
}
void Manacher(char *s_new,int *p){
int id=1,mx=0;
for(int i=1;i<=len;i++){
if(i<mx) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(s_new[i+p[i]]==s_new[i-p[i]]) p[i]++;
if(i+p[i]>mx){
id=i;
mx=i+p[i];
}
}
}
int query(){
int ans=1;
for(int i=2;i<=len;i++){
int tmp=max(lena[i],lenb[i-2]);
while(a_new[i-tmp]==b_new[i+tmp-2]) tmp++;
ans=max(ans,tmp);
}
return ans-1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n){
init(a_new);
init(b_new);
len=2*n+1;
Manacher(a_new,lena);
Manacher(b_new,lenb);
int ans=query();
cout<<ans<<endl;
}
return 0;
}
回文串
题目大意
最长回文子串长度Manacher模板
题解
注意我的模板代码里面n代表起初输入的字符串的长度
len代表的是经过变化后的字符串的长度
#include
using namespace std;
const int maxn=1e5+5;
int n,len;
char s[maxn],a_new[maxn*2];
int lena[maxn*2];
void init(char *s_new){
int j=1;
s_new[0]='$';
s_new[1]='#';
for(int i=0;i<n;i++){
s_new[++j]=s[i];
s_new[++j]='#';
}
s_new[++j]='\0';
}
int Manacher(char *s_new,int *p){
int id=1,mx=0;
int ans=1;
for(int i=1;i<len;i++){
if(i<mx) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(s_new[i+p[i]]==s_new[i-p[i]]) p[i]++;
if(i+p[i]>mx){
id=i;
mx=i+p[i];
}
ans=max(ans,p[i]-1);
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>s){
n=strlen(s);
init(a_new);
len=strlen(a_new);
cout<<Manacher(a_new,lena)<<endl;
}
return 0;
}
Codeforces Round #260 (Div. 1), problem: (A) Boredom
题目大意
dp,由题意推递推公式
题解
做法是先存下每个数的个数放在c中,消除一个数i,会获得 c[ i ] * i 的值(因为可以消除c[i]次),如果从0的位置开始向右消去,那么,消除数i时,i-1可能选择了消除,也可能没有
如果消除了i-1,那么i值就已经不存在,dp[i] = dp[i-1],如果没有被消除,那么dp[i] = dp[i-2]+ c[i]*i。
在上面两者中取最大值即可。
#include
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll a[maxn],dp[maxn];;
int n;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n){
for(int i=1;i<=n;i++){
ll x;
cin>>x;
a[x]++;
}
dp[1]=a[1];
for(int i=2;i<=maxn;i++){
dp[i]=max(dp[i-1],dp[i-2]+a[i]*i);
}
cout<<dp[maxn]<<endl;
}
return 0;
}
Codeforces Round #280 (Div. 2), problem: (B) Vanya and Lanterns
题目大意
求让路灯覆盖整个路的最小半径
题解
我们要考虑三个点,首先是起点附近的第一个路灯,其次是终点附近的第一个路灯,它们两个距离要取最大值 然后就是其他路灯,其它路灯的覆盖范围是它们位置之差的一半,要想覆盖整个路的话,需要从这三者当中求得一个最大值
#include
using namespace std;
int n,m;
typedef long long ll;
const int maxn=1e3+10;
ll a[maxn];
int main(){
while(cin>>n>>m){
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
double ans=max(a[0]-0,m-a[n-1]);
for(int i=1;i<n;i++)
ans=max(ans,(a[i]-a[i-1])/2.0);
printf("%.10f\n",ans);
}
return 0;
}
Codeforces Round #119 (Div. 2), problem: (A) Cut Ribbon
题目大意
给出一条丝带长度n,要求把丝带切成给定长度a、b、c中的一种或多种,问:最多能切成几条?(保证至少有一个解)
题解
按照题意就很明确是一个完全背包的题目,要将背包装满,然后又要最大化丝带个数(即最大价值)
#include
using namespace std;
const int maxn=1e4+10;
int a[maxn],dp[maxn];
int n;
const int INF=0x3f3f3f3f;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>a[0]>>a[1]>>a[2];
for(int i=1;i<=n;i++)
dp[i]=-INF;
dp[0]=0;
for(int i=0;i<=2;i++){
for(int j=a[i];j<=n;j++){
dp[j]=max(dp[j],dp[j-a[i]]+1);
}
}
cout<<dp[n]<<endl;
return 0;
}
另外附上完全背包,01背包,多重背包模板代码写的
#include
using namespace std;
const int maxn=1e4+10;
int a[maxn],dp[maxn],c[maxn];
int n;
const int INF=0x3f3f3f3f;
void CompletePack(int v,int w,int m)
{
for(int j=v; j<=m; j++)
dp[j] = max(dp[j],dp[j-v]+w);
}
void ZeroOnePack(int v,int w,int m)
{
for(int j=m; j>=v; j--)
dp[j] = max(dp[j],dp[j-v]+w);
}
void MultiPack(int v,int w,int m,int c)
{
if(v*c > m) CompletePack(v,w,m);
else
{
int k = 1;
while(k < c)
{
ZeroOnePack(k*v,k*w,m);
c -= k;
k *= 2;
}
ZeroOnePack(c*v,c*w,m);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>a[0]>>a[1]>>a[2];
for(int i=0;i<n;i++)
dp[i]=-INF;
dp[0]=0;
for(int i=0;i<3;i++)
CompletePack(a[i],1,n);
cout<<dp[n]<<endl;
return 0;
}
学如逆水行舟,不进则退