zoukankan      html  css  js  c++  java
  • P1435 回文字串 题解

    CSDN同步

    原题链接

    简要题意:

    给定一个长为 (n) 的字符串 (s),求至少插入多少个字符能使得 (s) 变成回文串。

    (n leq 10^3).

    ( ext{IOI2000}) 签到题,可以仔细看一下。

    这题个人用的区间 ( ext{dp}) 很有思考价值。

    可以思考一下:答案最大为 (n).显然直接把 ( ext{rev}(s)) 加到 (s) 后面就行(( ext{rev}) 表示翻转后的串),这样是 (n) 个字符。

    但是显然,对于 ( ext{rev}(s))(s) 中,相同的序列(序列不连续)可以选择跳过。就比方说,(s=) ab3bd( ext{rev}(s) =) db3ba,你会发现:

    (s) 的子序列 b3b( ext{rev}(s)) 的子序列 b3b 完全相同。那原来的答案是:ab3bddb3ba,实际上答案会是 adb3bda,相当于你把 ([) b3b , b3b (]) 除了两个 b3b ,其余的回文字符保持回文,丢到两边去;然后只剩下一个 b3b,这样答案 (-3). (5-3=2),可以证明是最优的。

    那么其实我们就是要找到 (s)( ext{rev}(s))最长公共子序列,然后一减即为答案!最长公共子序列怎么求呢?假设我们要求 (s)(t)最长公共子序列

    (f_{i,j}) 表示 s[1 ~ i]t [1 ~ j] 的答案。则:

    [ egin{cases} f_{i,j} = f_{i-1,j-1} + 1 space space space space space space space space space space space , s[i] = t[j] \ f_{i,j} = max(f_{i-1,j} , f_{i,j-1}) , s[i] ot = t[j] \ end{cases}]

    时间复杂度:(mathcal{O}(n^2)).

    实际得分:(100pts).

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=5e3+1;
    
    inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
    
    inline void write(int x) {
    	if(x<0) {putchar('-');write(-x);return;}
    	if(x<10) {putchar(char(x%10+'0'));return;}
    	write(x/10);putchar(char(x%10+'0'));
    }
    
    int n,f[N][N];
    char s1[N],s2[N];
    
    int main() {
    	scanf("%s",s1+1); n= strlen(s1+1);
    	for(int i=1;i<=n;i++) s2[i]=s1[n-i+1]; //下标从 1 开始 , 便于操作
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
    		if(s1[i]==s2[j]) f[i][j]=f[i-1][j-1]+1;
    		else f[i][j]=max(f[i-1][j],f[i][j-1]); //dp
    	printf("%d
    ",n-f[n][n]);	//答案
    	return 0;
    }
    
    
    
  • 相关阅读:
    Swift学习笔记(7)--控制流
    安装APK时报 Installation failed with message Failed to finalize session : INSTALL_FAILED_USER_RESTRICTED: Invalid apk.
    Android Notification 的四种使用方式
    Socket.io
    socket
    socket.io 中文手册 socket.io 中文文档
    Android中的CardView使用
    TabLayout实现底部导航栏(2)
    使用PagerSlidingTabStrip实现顶部导航栏
    TabLayout实现顶部导航栏(1)
  • 原文地址:https://www.cnblogs.com/bifanwen/p/13339907.html
Copyright © 2011-2022 走看看