1、构造回文
时间限制:1秒空间限制:32768K
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入例子1:
abcda google
输出例子1:
2 2
解法一:
分析:先求字符串s的反串reverse,然后求它们的最长的公共子序列,就能知道要删除的字符个数了。
C++程序如下:
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int MAXN=1010; //定义一个整型常量MAXN
int temp[MAXN][MAXN]; //声明一个数组temp
int getRemoveNumber(string &s1)
{
string s2(s1);
reverse(s2.begin(),s2.end()); //翻转s2
int len=s1.length(); //s1的长度
memset(temp,0,sizeof temp); //将temp所指向的某一块内存中的前(sizeof temp)个字节的内容全部设置为0
for(int i=0;i<len;++i)
{
for(int j=0;j<len;++j)
{
if(s1[i]==s2[j])
temp[i+1][j+1]=temp[i][j]+1;
else temp[i+1][j+1]=max(temp[i][j+1],temp[i+1][j]);
}
}
return len-temp[len][len];
}
int main()
{
string s;
while(cin>>s)
{
cout<<getRemoveNumber(s)<<endl;
}
return 0;
}【相关函数介绍】
memset函数:
函数原型: memset(void *s,int ch,size_t n)
函数说明:
memset函数是计算机中C/C++语言函数。将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值,第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为指向s的指针。所在头文件<memory.h>或<string.h>。
该函数的第二个参数ch为进行初始化的值,该值的范围为0到255(00000000到11111111)。如果超过该范围那么会对该值取后8位。如果ch为字符型,那么取其ASCII码。
1.对bool数组进行初始化:初始化结果为true或false
(1)使用 0或1初始化 memset(prime,0,sizeof(prime));0为false,1为true
(2)使用 true或false初始化 memset(prime,true,sizeof(prime));true为true,false为false
(3)使用其它值初始化 memset(prime,‘A’,sizeof(prime)); 非0值为true,0为false(字符0取ASCII码48,为true)
2.对char数组进行初始化:
(1)使用char型变量。memset(CH,‘A’,sizeof(CH));初始化结果为对应的字符。
(2)使用int型变量。将该int值作为ASCII码,使用对应的字符进行初始化。(0到127为ASCII码表,其中0为NULL,128到254未知,应该为扩展ASCII码。255显示字符串中字符无效。)
(3)使用bool型变量true或false。(true为ASCII码1,false为ASCII码0,初始结果同int)
3.对int数组进行初始化:
仅可在初始化的值的最后8位为11111111(255)或00000000(0)时能够正确进行初始化。也就是说int型数组仅能初始化为-1和0。其余方法均不能得到正确的结果。
解法二:
分析:本题可以转换为求该字符串与其反序字符串的最长公共子序列问题,即利用LCS算法求解。
例如:abcda的反序字符串为adcba,最长公共子序列为aba,其公共子序列必为回文序列,然后可求出最少删除多少个字节使其成为回文字符串。
本题采用动态规划来求解问题,下面看看模拟的推导过程。
状态转移方程为:(令A为输入字符串,B为其反序字符串,num[][]记录当前最长公共子序列的长度)
if (A[i] == B[j]) num[i][j] = num[i-1][j-1] + 1else num[i][j] = max(num[i-1][j] , num[i][j-1])
C++程序如下:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <string>
using namespace std;
int main(){
string s;
while(cin>>s){
int len = s.length();
int maxlen = 0;
vector<vector<int> > Vec;
for(int i = 0 ; i < len+1 ; i++){
vector<int> temp(len+1,0);
Vec.push_back(temp);
}
for(int i = 1; i< len+1 ; i++){
for(int j = 1 ; j < len+1;j++){
if(s[i-1]==s[len-j]){
Vec[i][j] = Vec[i-1][j-1]+1;
}
else {
Vec[i][j] = max(Vec[i-1][j],Vec[i][j-1]);
}
}
}
cout<<len-Vec[len][len]<<endl;
}
}2、字符移位
时间限制:1秒空间限制:32768K
小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
你能帮帮小Q吗?
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出移位后的字符串。
示例1
输入AkleBiCeilD
输出kleieilABCD
分析:如果碰到大写,就插入到字符串的最后面.
C++程序如下:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char a[1000];
while(cin>>a)
{
int len = strlen(a);
int end = len-1;
for(int i = 0; i<= end;)
{
if(a[i]>='A'&&a[i]<='Z')
{
char temp = a[i];
for(int j=i; j<len; j++)
{
a[j]=a[j+1];
}
a[len-1] = temp;
end--;
}
else i++;
}
cout<<a<<endl;
}
return 0;
}有趣的数字
小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,相差最小的有多少对呢?相差最大呢?
时间限制:1秒空间限制:32768K
输入描述:
输入包含多组测试数据。 对于每组测试数据: N - 本组测试数据有n个数 a1,a2...an - 需要计算的数据 保证: 1<=N<=100000,0<=ai<=INT_MAX.
输出描述:
对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。
示例1
输入645 12 45 32 5 6
输出1 2
分析:先排序,然后对有序数组分别求差值最大的对数和差值最小的对数。排序之后,差值最大的好求,看有序数组有几个最小值和几个最大值,相乘即可。差值最小的,由于是有序数组,必定是相邻的差值较小,故由排序后的有序数组求出差值最小值。如果差值最小值为0,则算出数组中相等的元素的对数;如果差值最小值不为0,则只需计算有多少个最小值即可。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
while (cin>>n) {
vector<int> nums(n);
for (int i=0; i<n; i++) {
cin>>nums[i];
}
int minNum=0, maxNum=0;
//排序
sort(nums.begin(), nums.end());
//最大
int m1 = 0, m2 = n-1, a=1, b=1;
while (nums[m1+1] == nums[m1]) {
a++;
m1++;
}
while (nums[m2] == nums[m2-1]) {
b++;
m2--;
}
maxNum = a*b;
//最小
int minTemp=nums[n-1];
for (int i=1; i<n; i++) {
if (nums[i]-nums[i-1]<minTemp) {
minTemp = nums[i]-nums[i-1];
}
}
if (minTemp >0) {
for (int i=1; i<n; i++) {
if (nums[i]-nums[i-1] == minTemp) {
minNum++;
}
}
}else{
for (int i=1; i<n; i++) {
int j=i-1;
while (nums[j]==nums[i] && j>=0) {
minNum++;
j--;
}
}
}
cout<<minNum<<" "<<maxNum<<endl;
}
return 0;
}
京公网安备 11010502036488号